// bdlde_charconvertutf32.t.cpp                                       -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------


#include <bdlde_charconvertutf32.h>

#include <bdlde_charconvertstatus.h>
#include <bdlde_utf8util.h>

#include <bdlb_random.h>

#include <bsls_assert.h>
#include <bsls_asserttest.h>
#include <bsls_byteorderutil.h>
#include <bsls_review.h>
#include <bsls_stopwatch.h>
#include <bsls_types.h>

#include <bsl_algorithm.h>
#include <bsl_iomanip.h>
#include <bsl_iostream.h>
#include <bsl_sstream.h>

#include <bsl_cstdlib.h>
#include <bsl_cstring.h>
#include <bsl_cctype.h>

using namespace BloombergLP;

using bsl::cout;
using bsl::cerr;
using bsl::endl;
using bsl::flush;
using bsl::size_t;

// ============================================================================
//                                TEST PLAN
// Concerns:
//: o That the translators never segfault or fail for any possible input
//:   stream.
//: o That output to STL containers never overflow the size of the container
//:   (functions with container destinations estimate output size.  The size
//:   estimation functions are not public and cannot be tested directly, but
//:   there are safe asserts in the container destination functions that
//:   verify the accuracy of these estimates, enhancing the effectiveness
//:   of the testing).
//: o The output is correct.  This can be verified using tables of sample input
//:   and corresponding expected output.  Sequences of input randomly selected
//:   from the table and spliced together should generate the corresponding
//:   output spliced together.
//: o If a fixed-length buffer is provided, the memory after the first
//:   'capacity' bytes or words is never written to.
//: o If a fixed-length buffer is provided and insufficient capacity is
//:   provided, as many code points as will fit are written.  This means that
//:   if the destination is UTF-32, exactly 'capacity' words will be written.
//:   1 If a fixed-length buffer is provided and a '0 == capacity', nothing is
//:     written to the destination and the out of space bit is set in the
//:     return value.
//: o Preconditions are asserted before any modification of the output is
//:   performed.
//: o That every type of UTF-8 error is detected and appropriately handled.
//: o That invalid UTF-32 code points are detected and appropriately handled.
//: o All forms of valid input and all forms of errors should be handled the
//:   same whether at the beginning, the end or in the middle of a sequence.
//: o The invalid input bit returned always properly reflects whether any
//:   invalid input was encountered (prior to running out of space).
//: o The out of space bit returned always properly reflects whether the
//:   capacity specified was adequate, and is never set on translations with
//:   STL container output destinations.
// ----------------------------------------------------------------------------
// [17] USAGE EXAMPLE
// [16] UTF-32 <- UTF-8 Random garbage input, random error word
// [15] UTF-32 <- UTF-8 Table generated random sequences, random error word
// [14] UTF-8 <- UTF-32 Random garbage input, random error byte
// [13] UTF-8 <- UTF-32 Table generated random sequences, 0 error byte
// [12] UTF-8 <- UTF-32 Table generated random sequences, default error byte
// [11] Translating real prose in 4 languages, both directions
// [10] Negative testing, all functions, all conditions
// [ 9] UTF-8 <- UTF-32 to vector, string, buffer, passing non-zero error byte
// [ 8] UTF-8 <- UTF-32 to vector, string, buffer, 0 error byte
// [ 7] UTF-8 <- UTF-32 to vector, string, buffer, default error byte
// [ 6] UTF-32 <- UTF-8 Translation to vector, passing non-zero error word
// [ 5] UTF-32 <- UTF-8 Translation to vector, 0 error word
// [ 4] UTF-32 <- UTF-8 Translation to fixed-length buffers, 0 error word
// [ 3] UTF-32 <- UTF-8 Translation to vector, default error word
// [ 2] UTF-32 <- UTF-8 Translation to fixed-length buffers, default error word
// [ 1] Breathing Test
// ----------------------------------------------------------------------------

// ============================================================================
//                 MODIFIED "STANDARD" BDE ASSERT TEST MACRO
// ----------------------------------------------------------------------------

namespace {
int testStatus = 0;

bool aSsErT(int c, const char *s, int i)
{
    if (c) {
        cout << "Error " << __FILE__ << "(" << i << "): " << s
             << "    (failed)" << endl;
        if (testStatus >= 0 && testStatus <= 100) {
            ++testStatus;
        }
    }
    return c == 0;
}

}  // close unnamed namespace

#define ASSERT(X) ( aSsErT(!(X), #X, __LINE__) )

// ============================================================================
//                   STANDARD BDE LOOP-ASSERT TEST MACROS
// ----------------------------------------------------------------------------

#define LOOP_ASSERT(I,X) { \
   if (!(X)) { cout << #I << ": " << I << "\n"; aSsErT(1, #X, __LINE__); }}

#define LOOP2_ASSERT(I,J,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " \
              << J << "\n"; aSsErT(1, #X, __LINE__); } }

#define LOOP3_ASSERT(I,J,K,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" \
              << #K << ": " << K << "\n"; aSsErT(1, #X, __LINE__); } }

#define LOOP4_ASSERT(I,J,K,L,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" << \
       #K << ": " << K << "\t" << #L << ": " << L << "\n"; \
       aSsErT(1, #X, __LINE__); } }

#define LOOP5_ASSERT(I,J,K,L,M,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" << \
       #K << ": " << K << "\t" << #L << ": " << L << "\t" << \
       #M << ": " << M << "\n"; \
       aSsErT(1, #X, __LINE__); } }

#define LOOP6_ASSERT(I,J,K,L,M,N,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" << \
       #K << ": " << K << "\t" << #L << ": " << L << "\t" << \
       #M << ": " << M << "\t" << #N << ": " << N << "\n"; \
       aSsErT(1, #X, __LINE__); } }

#define LOOP7_ASSERT(I,J,K,L,M,N,P,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" << \
       #K << ": " << K << "\t" << #L << ": " << L << "\t" << \
       #M << ": " << M << "\t" << #N << ": " << N << "\t" << \
       #P << ": " << P << "\n"; \
       aSsErT(1, #X, __LINE__); } }

#define LOOP8_ASSERT(I,J,K,L,M,N,P,Q,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" << \
       #K << ": " << K << "\t" << #L << ": " << L << "\t" << \
       #M << ": " << M << "\t" << #N << ": " << N << "\t" << \
       #P << ": " << P << "\t" << #Q << ": " << Q << "\n"; \
       aSsErT(1, #X, __LINE__); } }

// ============================================================================
//                     SEMI-STANDARD TEST OUTPUT MACROS
// ----------------------------------------------------------------------------

#define P(X) cout << #X " = " << (X) << endl; // Print identifier and value.
#define Q(X) cout << "<| " #X " |>" << endl;  // Quote identifier literally.
#define P_(X) cout << #X " = " << (X) << ", "<< flush; // P(X) without '\n'
#define L_ __LINE__                           // current Line number
#define T_ cout << "\t" << flush;             // Print tab w/o newline

// ============================================================================
//                         CUSTOM TEST OUTPUT MACROS
// ----------------------------------------------------------------------------

#define R(X) #X " = " << (X)
#define R_(X) #X " = " << (X) << " "

// ============================================================================
//                     NEGATIVE-TEST MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT_FAIL(expr) BSLS_ASSERTTEST_ASSERT_FAIL(expr)
#define ASSERT_PASS(expr) BSLS_ASSERTTEST_ASSERT_PASS(expr)
#define ASSERT_SAFE_FAIL(expr) BSLS_ASSERTTEST_ASSERT_SAFE_FAIL(expr)
#define ASSERT_SAFE_PASS(expr) BSLS_ASSERTTEST_ASSERT_SAFE_PASS(expr)

// ============================================================================
//                              GLOBAL TYPEDEFS
// ----------------------------------------------------------------------------

typedef bdlde::CharConvertUtf32  Util;
typedef bdlde::CharConvertStatus Status;
typedef bdlde::Utf8Util          Utf8Util;
typedef bsls::Types::UintPtr     UintPtr;
typedef bsls::Types::IntPtr      IntPtr;

// ============================================================================
//                           CUSTOM TEST APPARATUS
// ----------------------------------------------------------------------------

bool verbose;
bool veryVerbose;
bool veryVeryVerbose;
bool veryVeryVeryVerbose;
bool veryVeryVeryVeryVerbose;

bdlde::ByteOrder::Enum oppositeEndian =
                     bdlde::ByteOrder::e_BIG_ENDIAN == bdlde::ByteOrder::e_HOST
                     ? bdlde::ByteOrder::e_LITTLE_ENDIAN
                     : bdlde::ByteOrder::e_BIG_ENDIAN;

const void *hx(bsls::Types::UintPtr val)
    // Cast the specified 'val' to 'void *' so it will be printed in hex
{
    return (const void *) val;
}

template <class TYPE>
TYPE sb(TYPE x)
{
    return bsls::ByteOrderUtil::swapBytes(x);
}

unsigned char utf8MultiLang[] = {
    239, 187, 191, 'C', 'h', 'i', 'n', 'e', 's', 'e', ':',  13,
     10,  13,  10, 228, 184, 173, 229, 141, 142, 228, 186, 186,
    230, 176, 145, 229, 133, 177, 229, 146, 140, 229, 155, 189,
    239, 188, 140, 233, 128, 154, 231, 167, 176, 228, 184, 173,
    229, 155, 189, '[', 230, 179, 168, ' ', '3', ']', 239, 188,
    140, 230, 152, 175, 228, 189, 141, 230, 150, 188, 228, 186,
    154, 230, 180, 178, 230, 157, 177, 233, 131, 168, 227, 128,
    129, 229, 164, 170, 229, 185, 179, 230, 180, 139, 232, 165,
    191, 229, 178, 184, 231, 154, 132, 228, 184, 128, 228, 184,
    170, 231, 164, 190, 228, 188, 154, 228, 184, 187, 228, 185,
    137, 229, 155, 189, 229, 174, 182, 227, 128, 130, 233, 166,
    150, 233, 131, 189, 231, 130, 186, 229, 140, 151, 228, 186,
    172, 227, 128, 130, 229, 133, 182, 233, 153, 134, 229, 156,
    176, 231, 150, 134, 229, 159, 159, 232, 136, 135, 229, 145,
    168, 233, 130, 138, '1', '4', 229, 128, 139, 229, 156, 139,
    229, 174, 182, 230, 142, 165, 229, 163, 164, 239, 188, 140,
    233, 153, 134, 229, 156, 176, 229, 143, 138, 230, 185, 150,
    230, 179, 138, 231, 154, 132, 230, 128, 187, 233, 157, 162,
    231, 169, 141, 231, 186, 166, '9', '6', '0', 232, 144, 172,
    229, 185, 179, 230, 150, 185, 229, 133, 172, 233, 135, 140,
    '[', '1', '1', ']', '[', '1', '2', ']', '[', '1', '3', ']',
    239, 188, 140, 230, 152, 175, 229, 133, 168, 228, 184, 150,
    231, 149, 140, 233, 153, 134, 229, 156, 176, 233, 157, 162,
    231, 167, 175, 231, 172, 172, 228, 186, 140, 229, 164, 167,
    231, 154, 132, 229, 155, 189, 229, 174, 182, 239, 188, 140,
    230, 128, 187, 233, 157, 162, 231, 167, 175, 231, 172, 172,
    228, 184, 137, 230, 136, 150, 231, 172, 172, 229, 155, 155,
    229, 164, 167, 231, 154, 132, 229, 155, 189, 229, 174, 182,
    227, 128, 130, 229, 133, 182, 228, 186, 186, 229, 143, 163,
    232, 182, 133, 233, 129, 142, '1', '3', 229, 132, 132, 239,
    188, 140, 231, 180, 132, 228, 189, 148, 229, 133, 168, 231,
    144, 131, 228, 186, 186, 229, 143, 163, 231, 154, 132, 228,
    186, 148, 229, 136, 134, 228, 185, 139, 228, 184, 128, 239,
    188, 140, 230, 152, 175, 228, 184, 150, 231, 149, 140, 228,
    184, 138, 228, 186, 186, 229, 143, 163, 230, 156, 128, 229,
    164, 154, 231, 154, 132, 229, 156, 139, 229, 174, 182, 227,
    128, 130,  13,  10,  13,  10, 228, 189, 156, 231, 130, 186,
    231, 164, 190, 228, 188, 154, 228, 184, 187, 228, 185, 137,
    229, 155, 189, 229, 174, 182, 239, 188, 140, 228, 184, 173,
    232, 143, 175, 228, 186, 186, 230, 176, 145, 229, 133, 177,
    229, 146, 140, 229, 156, 139, 228, 187, 165, 233, 169, 172,
    229, 133, 139, 230, 128, 157, 229, 136, 151, 229, 174, 129,
    228, 184, 187, 228, 185, 137, 231, 130, 186, 230, 132, 143,
    232, 173, 152, 229, 189, 162, 230, 133, 139, 239, 188, 140,
    228, 190, 157, 228, 184, 173, 229, 156, 139, 231, 137, 185,
    232, 137, 178, 231, 164, 190, 230, 156, 131, 228, 184, 187,
    231, 190, 169, 231, 144, 134, 232, 174, 186, 230, 140, 135,
    229, 176, 142, 230, 148, 191, 228, 186, 139, 239, 188, 140,
    229, 185, 182, 231, 148, 177, 230, 134, 178, 230, 179, 149,
    230, 137, 128, 232, 179, 166, 228, 186, 136, 228, 184, 173,
    229, 155, 189, 229, 133, 177, 228, 186, 167, 229, 133, 154,
    229, 159, 183, 230, 148, 191, 239, 188, 140, 229, 174, 158,
    232, 161, 140, 228, 184, 173, 229, 155, 189, 229, 133, 177,
    228, 186, 167, 229, 133, 154, 233, 162, 134, 229, 175, 188,
    231, 154, 132, 229, 164, 154, 229, 133, 154, 229, 144, 136,
    228, 189, 156, 229, 146, 140, 230, 148, 191, 230, 178, 187,
    229, 141, 143, 229, 149, 134, 229, 136, 182, 229, 186, 166,
    '[', '1', '4', ']', 227, 128, 130, '1', '9', '4', '9', 229,
    185, 180, '1', '0', 230, 156, 136, '1', 230, 151, 165, 231,
    154, 132, 229, 188, 128, 229, 155, 189, 229, 164, 167, 229,
    133, 184, 228, 184, 173, 239, 188, 140, 228, 184, 173, 229,
    141, 142, 228, 186, 186, 230, 176, 145, 229, 133, 177, 229,
    146, 140, 229, 155, 189, 228, 184, 173, 229, 164, 174, 228,
    186, 186, 230, 176, 145, 230, 148, 191, 229, 186, 156, 230,
    173, 163, 229, 188, 143, 229, 174, 163, 229, 145, 138, 230,
    136, 144, 231, 171, 139, '[', 230, 179, 168, ' ', '4', ']',
    227, 128, 130, 229, 133, 168, 229, 156, 139, 229, 138, 131,
    229, 136, 134, 231, 130, 186, '2', '3', 229, 128, 139, 231,
    156, 129, 239, 188, 136, 229, 133, 182, 228, 184, 173, 229,
    185, 182, 230, 178, 161, 230, 156, 137, 229, 175, 185, 229,
    143, 176, 230, 185, 190, 231, 156, 129, 229, 133, 168, 233,
    131, 168, 228, 184, 142, 231, 166, 143, 229, 187, 186, 231,
    156, 129, 227, 128, 129, 230, 181, 183, 229, 141, 151, 231,
    156, 129, 233, 131, 168, 229, 136, 134, 229, 156, 176, 229,
    140, 186, 229, 174, 158, 233, 153, 133, 231, 174, 161, 232,
    190, 150, 239, 188, 137, 227, 128, 129, '5', 229, 128, 139,
    232, 135, 170, 230, 178, 187, 229, 141, 128, 227, 128, 129,
    '4', 229, 128, 139, 231, 155, 180, 232, 190, 150, 229, 184,
    130, 229, 146, 140, '2', 229, 128, 139, 231, 137, 185, 229,
    136, 165, 232, 161, 140, 230, 148, 191, 229, 140, 186, 239,
    188, 136, 229, 141, 179, 233, 166, 153, 230, 184, 175, 232,
    136, 135, 230, 190, 179, 233, 150, 128, 239, 188, 137, 239,
    188, 140, 231, 156, 129, 231, 186, 167, 228, 186, 186, 230,
    176, 145, 230, 148, 191, 229, 186, 156, 229, 143, 151, 229,
    155, 189, 229, 138, 161, 233, 153, 162, 233, 162, 134, 229,
    175, 188, 239, 188, 140, 231, 137, 185, 229, 136, 165, 232,
    161, 140, 230, 148, 191, 229, 141, 128, 229, 137, 135, 230,
    160, 185, 230, 147, 154, 228, 184, 128, 229, 156, 139, 229,
    133, 169, 229, 136, 182, 230, 148, 191, 231, 173, 150, 229,
    175, 166, 232, 161, 140, 233, 171, 152, 229, 186, 166, 232,
    135, 170, 230, 178, 187, 227, 128, 130, 229, 133, 168, 229,
    155, 189, 232, 183, 168, 232, 182, 138, 228, 186, 148, 228,
    184, 170, 229, 156, 176, 231, 144, 134, 230, 151, 182, 229,
    140, 186, 239, 188, 140, 228, 189, 134, 229, 157, 135, 228,
    189, 191, 231, 148, 168, 228, 184, 173, 229, 156, 139, 230,
    168, 153, 230, 186, 150, 230, 153, 130, 233, 150, 147, 239,
    188, 136, 229, 141, 179, 'U', 'T', 'C', '+', '8', 239, 188,
    137, 227, 128, 130,  13,  10,  13,  10, 228, 184, 173, 232,
    143, 175, 228, 186, 186, 230, 176, 145, 229, 133, 177, 229,
    146, 140, 229, 156, 139, 230, 152, 175, 229, 164, 154, 230,
    176, 145, 230, 151, 143, 229, 155, 189, 229, 174, 182, 239,
    188, 140, 229, 133, 182, 228, 184, 173, 230, 177, 137, 230,
    151, 143, 228, 189, 148, 231, 184, 189, 228, 186, 186, 229,
    143, 163, 231, 154, 132, '9', '1', '.', '5', '9', '%', 239,
    188, 140, 229, 133, 182, 233, 164, 152, '5', '5', 228, 184,
    170, 230, 176, 145, 230, 151, 143, 231, 130, 186, 229, 176,
    145, 230, 149, 176, 230, 176, 145, 230, 151, 143, 239, 188,
    140, 229, 155, 189, 229, 174, 182, 232, 170, 141, 229, 174,
    154, 231, 154, 132, '5', '6', 229, 128, 139, 230, 176, 145,
    230, 151, 143, 229, 144, 136, 231, 167, 176, 226, 128, 156,
    228, 184, 173, 229, 141, 142, 230, 176, 145, 230, 151, 143,
    226, 128, 157, 227, 128, 130, 228, 184, 173, 229, 141, 142,
    228, 186, 186, 230, 176, 145, 229, 133, 177, 229, 146, 140,
    229, 155, 189, 230, 156, 137, '2', '4', 231, 167, 141, 230,
    176, 145, 230, 151, 143, 230, 150, 135, 229, 173, 151, 239,
    188, 140, 229, 133, 171, 229, 141, 129, 229, 164, 154, 231,
    167, 141, 230, 176, 145, 230, 151, 143, 232, 175, 173, 232,
    168, 128, 227, 128, 130, 228, 184, 173, 229, 141, 142, 228,
    186, 186, 230, 176, 145, 229, 133, 177, 229, 146, 140, 229,
    155, 189, 230, 178, 161, 230, 156, 137, 230, 152, 142, 231,
    161, 174, 232, 167, 132, 229, 174, 154, 231, 154, 132, 229,
    155, 189, 229, 174, 182, 232, 175, 173, 232, 168, 128, 239,
    188, 140, 228, 187, 165, 230, 177, 137, 232, 175, 173, 230,
    153, 174, 233, 128, 154, 232, 175, 157, 229, 146, 140, 232,
    167, 132, 232, 140, 131, 231, 174, 128, 229, 140, 150, 230,
    177, 137, 229, 173, 151, 228, 184, 186, 226, 128, 156, 229,
    155, 189, 229, 174, 182, 233, 128, 154, 231, 148, 168, 232,
    175, 173, 232, 168, 128, 230, 150, 135, 229, 173, 151, 226,
    128, 157, '[', 230, 179, 168, ' ', '5', ']', 227, 128, 130,
    228, 184, 173, 229, 155, 189, 228, 188, 160, 231, 187, 159,
    228, 184, 138, 230, 152, 175, 228, 187, 165, 231, 165, 150,
    229, 133, 136, 228, 191, 161, 228, 187, 176, 228, 184, 186,
    228, 184, 187, 231, 154, 132, 229, 155, 189, 229, 174, 182,
    239, 188, 140, 229, 185, 182, 229, 133, 183, 230, 156, 137,
    229, 132, 146, 233, 135, 138, 233, 129, 147, 228, 184, 137,
    230, 149, 153, 229, 144, 136, 230, 181, 129, 231, 154, 132,
    229, 174, 151, 230, 149, 153, 228, 191, 161, 228, 187, 176,
    228, 188, 160, 231, 187, 159, 229, 146, 140, 231, 137, 185,
    231, 130, 185, 239, 188, 140, 229, 144, 140, 230, 151, 182,
    229, 173, 152, 229, 156, 168, 229, 133, 182, 229, 174, 131,
    229, 164, 154, 231, 167, 141, 229, 174, 151, 230, 149, 153,
    227, 128, 130, 228, 184, 173, 229, 141, 142, 228, 186, 186,
    230, 176, 145, 229, 133, 177, 229, 146, 140, 229, 155, 189,
    229, 144, 142, 239, 188, 140, 229, 174, 152, 230, 150, 185,
    229, 165, 137, 232, 161, 140, 230, 151, 160, 231, 165, 158,
    232, 174, 186, 239, 188, 140, 229, 133, 182, 229, 144, 142,
    230, 155, 190, 229, 143, 145, 229, 138, 168, 231, 154, 132,
    230, 150, 135, 229, 140, 150, 229, 164, 167, 233, 157, 169,
    229, 145, 189, 229, 175, 185, 229, 144, 132, 231, 167, 141,
    229, 174, 151, 230, 149, 153, 233, 128, 160, 230, 136, 144,
    228, 184, 165, 233, 135, 141, 231, 160, 180, 229, 157, 143,
    239, 188, 140, 231, 155, 180, 229, 136, 176, 230, 148, 185,
    233, 157, 169, 229, 188, 128, 230, 148, 190, 229, 144, 142,
    230, 137, 141, 230, 156, 137, 230, 137, 128, 232, 189, 172,
    229, 143, 152, 227, 128, 130, 229, 189, 147, 228, 187, 138,
    228, 184, 173, 229, 155, 189, 230, 148, 191, 229, 186, 156,
    229, 175, 185, 229, 174, 151, 230, 149, 153, 228, 184, 142,
    228, 188, 160, 231, 187, 159, 228, 186, 139, 231, 137, 169,
    233, 135, 135, 229, 143, 150, 228, 191, 157, 230, 138, 164,
    231, 154, 132, 230, 128, 129, 229, 186, 166, 227, 128, 130,
     13,  10,  13,  10, 228, 184, 173, 229, 141, 142, 228, 186,
    186, 230, 176, 145, 229, 133, 177, 229, 146, 140, 229, 155,
    189, 230, 152, 175, 229, 155, 189, 233, 153, 133, 231, 164,
    190, 228, 188, 154, 231, 154, 132, 233, 135, 141, 232, 166,
    129, 228, 184, 128, 229, 145, 152, 239, 188, 140, 228, 185,
    159, 230, 152, 175, 228, 188, 151, 229, 164, 154, 230, 173,
    163, 229, 188, 143, 229, 146, 140, 233, 157, 158, 230, 173,
    163, 229, 188, 143, 231, 154, 132, 229, 164, 154, 232, 190,
    185, 231, 187, 132, 231, 187, 135, 231, 154, 132, 230, 136,
    144, 229, 145, 152, 239, 188, 140, 229, 140, 133, 230, 139,
    172, 232, 129, 148, 229, 144, 136, 229, 155, 189, 227, 128,
    129, 228, 184, 150, 231, 149, 140, 232, 180, 184, 230, 152,
    147, 231, 187, 132, 231, 187, 135, 227, 128, 129, 228, 186,
    154, 229, 164, 170, 231, 187, 143, 229, 144, 136, 231, 187,
    132, 231, 187, 135, 227, 128, 129, 233, 135, 145, 231, 160,
    150, 229, 155, 155, 229, 155, 189, 227, 128, 129, 228, 184,
    138, 230, 181, 183, 229, 144, 136, 228, 189, 156, 231, 187,
    132, 231, 187, 135, 229, 146, 140, '2', '0', 229, 155, 189,
    233, 155, 134, 229, 155, 162, 231, 173, 137, 239, 188, 140,
    228, 184, 186, 232, 129, 148, 229, 144, 136, 229, 155, 189,
    229, 174, 137, 229, 133, 168, 231, 144, 134, 228, 186, 139,
    228, 188, 154, 229, 184, 184, 228, 187, 187, 231, 144, 134,
    228, 186, 139, 229, 155, 189, 227, 128, 129, 228, 184, 150,
    231, 149, 140, 231, 172, 172, 228, 186, 140, 229, 164, 167,
    231, 187, 143, 230, 181, 142, 228, 189, 147, 239, 188, 140,
    230, 152, 175, 228, 184, 150, 231, 149, 140, 231, 172, 172,
    228, 184, 128, 229, 164, 167, 229, 135, 186, 229, 143, 163,
    229, 156, 139, 227, 128, 129, 228, 184, 150, 231, 149, 140,
    231, 172, 172, 228, 186, 140, 229, 164, 167, 233, 128, 178,
    229, 143, 163, 229, 156, 139, 239, 188, 140, 230, 147, 129,
    230, 156, 137, 230, 156, 128, 229, 164, 154, 231, 154, 132,
    229, 164, 150, 230, 177, 135, 229, 132, 178, 229, 130, 153,
    239, 188, 140, 230, 156, 128, 228, 184, 176, 229, 175, 140,
    231, 154, 132, 228, 184, 150, 231, 149, 140, 230, 150, 135,
    229, 140, 150, 233, 129, 151, 228, 186, 167, 239, 188, 140,
    228, 186, 166, 230, 152, 175, 228, 184, 150, 231, 149, 140,
    228, 184, 138, 231, 187, 143, 230, 181, 142, 230, 136, 144,
    233, 149, 183, 230, 156, 128, 229, 191, 171, 231, 154, 132,
    229, 156, 139, 229, 174, 182, 228, 185, 139, 228, 184, 128,
    227, 128, 130, 229, 143, 166, 229, 164, 150, 239, 188, 140,
    228, 184, 173, 229, 155, 189, 230, 139, 165, 230, 156, 137,
    228, 184, 150, 231, 149, 140, 228, 184, 138, 231, 142, 176,
    229, 189, 185, 229, 163, 171, 229, 133, 181, 230, 156, 128,
    229, 164, 154, 231, 154, 132, 229, 134, 155, 233, 152, 159,
    239, 188, 155, 229, 134, 155, 228, 186, 139, 229, 188, 128,
    230, 148, 175, 228, 184, 150, 231, 149, 140, 231, 172, 172,
    228, 186, 140, 239, 188, 140, 230, 139, 165, 230, 156, 137,
    230, 160, 184, 230, 173, 166, 229, 153, 168, 239, 188, 140,
    229, 185, 182, 229, 133, 183, 229, 164, 135, 229, 143, 145,
    229, 176, 132, 229, 141, 171, 230, 152, 159, 227, 128, 129,
    232, 175, 149, 233, 170, 140, 229, 158, 139, 231, 169, 186,
    233, 151, 180, 231, 171, 153, 229, 146, 140, 230, 156, 136,
    231, 144, 131, 229, 143, 138, 230, 183, 177, 231, 169, 186,
    230, 142, 162, 230, 181, 139, 229, 153, 168, 231, 154, 132,
    232, 131, 189, 229, 138, 155, 239, 188, 155, '2', '0', '0',
    '3', 229, 185, 180, 239, 188, 140, 228, 184, 173, 229, 155,
    189, 230, 136, 144, 228, 184, 186, 228, 184, 150, 231, 149,
    140, 231, 172, 172, 228, 184, 137, 228, 184, 170, 232, 135,
    170, 228, 184, 187, 230, 136, 144, 229, 138, 159, 229, 143,
    145, 229, 176, 132, 232, 189, 189, 228, 186, 186, 232, 136,
    170, 229, 164, 169, 229, 153, 168, 231, 154, 132, 229, 155,
    189, 229, 174, 182, 227, 128, 130, 228, 184, 173, 229, 155,
    189, 228, 186, 166, 230, 152, 175, 230, 189, 156, 229, 156,
    168, 232, 182, 133, 231, 186, 167, 229, 164, 167, 229, 155,
    189, 228, 185, 139, 228, 184, 128, 239, 188, 140, 232, 162,
    171, 232, 174, 164, 228, 184, 186, 230, 152, 175, 228, 184,
    139, 228, 184, 128, 228, 189, 141, 232, 182, 133, 231, 186,
    167, 229, 164, 167, 229, 155, 189, 231, 154, 132, 230, 156,
    137, 229, 138, 155, 229, 128, 153, 233, 128, 137, 228, 186,
    186, 227, 128, 130,  13,  10,  13,  10, 228, 184, 173, 229,
    141, 142, 228, 186, 186, 230, 176, 145, 229, 133, 177, 229,
    146, 140, 229, 155, 189, 231, 154, 132, 230, 173, 163, 229,
    188, 143, 229, 155, 189, 229, 144, 141, 228, 186, 142, '1',
    '9', '4', '9', 229, 185, 180, 231, 148, 177, 228, 184, 173,
    229, 156, 139, 228, 186, 186, 230, 176, 145, 230, 148, 191,
    230, 178, 187, 229, 141, 148, 229, 149, 134, 230, 156, 131,
    232, 173, 176, 231, 177, 140, 229, 130, 153, 230, 156, 131,
    232, 173, 176, 231, 162, 186, 229, 174, 154, 239, 188, 140,
    229, 189, 147, 229, 136, 157, 230, 155, 190, 229, 138, 160,
    232, 168, 187, 227, 128, 140, 231, 176, 161, 231, 168, 177,
    239, 188, 154, 228, 184, 173, 232, 143, 175, 230, 176, 145,
    229, 156, 139, 227, 128, 141, 239, 188, 140, 228, 189, 134,
    229, 143, 184, 229, 190, 146, 231, 190, 142, 229, 160, 130,
    231, 173, 137, 230, 176, 145, 228, 184, 187, 229, 133, 154,
    230, 180, 190, 228, 186, 186, 229, 163, 171, 232, 174, 164,
    228, 184, 186, 230, 150, 176, 228, 184, 173, 229, 155, 189,
    229, 186, 148, 231, 161, 174, 231, 171, 139, 230, 150, 176,
    229, 155, 189, 229, 144, 141, 239, 188, 140, 228, 187, 165,
    231, 164, 186, 228, 184, 164, 230, 172, 161, 233, 157, 169,
    229, 145, 189, 231, 154, 132, 230, 160, 185, 230, 156, 172,
    230, 132, 143, 228, 185, 137, 228, 184, 141, 229, 144, 140,
    '[', '1', '5', ']', 227, 128, 130, 229, 155, 160, 230, 173,
    164, 231, 155, 180, 232, 135, 179, '9', 230, 156, 136, '2',
    '7', 230, 151, 165, 230, 148, 191, 229, 141, 148, 229, 133,
    168, 233, 171, 148, 230, 156, 131, 232, 173, 176, 232, 161,
    168, 230, 177, 186, 233, 128, 154, 233, 129, 142, 228, 184,
    173, 229, 164, 174, 228, 186, 186, 230, 176, 145, 230, 148,
    191, 229, 186, 156, 231, 181, 132, 231, 185, 148, 230, 179,
    149, 230, 153, 130, 239, 188, 140, 230, 173, 163, 229, 188,
    143, 232, 173, 176, 230, 177, 186, 229, 142, 187, 233, 153,
    164, 230, 173, 164, 229, 138, 160, 232, 168, 187, '[', '1',
    '6', ']', 227, 128, 130,  13,  10,  13,  10, 229, 156, 168,
    229, 133, 168, 233, 131, 168, 229, 156, 139, 233, 154, 155,
    229, 160, 180, 229, 144, 136, 239, 188, 140, 228, 184, 173,
    232, 143, 175, 228, 186, 186, 230, 176, 145, 229, 133, 177,
    229, 146, 140, 229, 156, 139, 228, 184, 128, 232, 136, 172,
    231, 176, 161, 231, 168, 177, 231, 130, 186, 228, 184, 173,
    229, 156, 139, 239, 188, 140, 230, 156, 137, 230, 151, 182,
    229, 128, 153, 228, 185, 159, 229, 155, 160, 229, 133, 182,
    230, 137, 128, 229, 164, 132, 229, 156, 176, 231, 144, 134,
    228, 189, 141, 231, 189, 174, 232, 128, 140, 232, 162, 171,
    231, 167, 176, 228, 184, 186, 228, 184, 173, 229, 155, 189,
    229, 164, 167, 233, 153, 134, 227, 128, 130, 229, 156, 168,
    228, 184, 173, 229, 156, 139, 229, 156, 139, 229, 133, 167,
    239, 188, 140, 231, 149, 182, '1', '9', '4', '9', 229, 185,
    180, 229, 137, 141, 231, 154, 132, 228, 184, 173, 232, 143,
    175, 230, 176, 145, 229, 156, 139, 232, 136, 135, '1', '9',
    '4', '9', 229, 185, 180, 229, 190, 140, 231, 154, 132, 228,
    184, 173, 232, 143, 175, 228, 186, 186, 230, 176, 145, 229,
    133, 177, 229, 146, 140, 229, 156, 139, 229, 129, 154, 229,
    176, 141, 230, 175, 148, 230, 136, 150, 230, 156, 137, 230,
    173, 164, 230, 182, 181, 230, 140, 135, 230, 153, 130, 239,
    188, 140, 229, 137, 141, 232, 128, 133, 229, 184, 184, 232,
    162, 171, 231, 168, 177, 231, 130, 186, 232, 136, 138, 228,
    184, 173, 229, 156, 139, 239, 188, 136, 228, 186, 166, 231,
    168, 177, 232, 136, 138, 231, 164, 190, 230, 156, 131, 239,
    188, 137, 239, 188, 140, 232, 128, 140, 229, 190, 140, 232,
    128, 133, 229, 137, 135, 229, 184, 184, 232, 162, 171, 231,
    168, 177, 231, 130, 186, 230, 150, 176, 228, 184, 173, 229,
    156, 139, 227, 128, 130, 231, 155, 174, 229, 137, 141, 239,
    188, 140, 228, 184, 173, 232, 143, 175, 228, 186, 186, 230,
    176, 145, 229, 133, 177, 229, 146, 140, 229, 156, 139, 232,
    170, 141, 231, 130, 186, 228, 184, 173, 232, 143, 175, 230,
    176, 145, 229, 156, 139, 229, 183, 178, 232, 162, 171, 229,
    133, 182, 229, 143, 150, 228, 187, 163, 239, 188, 140, 228,
    184, 173, 232, 143, 175, 230, 176, 145, 229, 156, 139, 230,
    148, 191, 229, 186, 156, 229, 137, 135, 228, 184, 141, 230,
    137, 191, 232, 170, 141, 228, 184, 173, 232, 143, 175, 228,
    186, 186, 230, 176, 145, 229, 133, 177, 229, 146, 140, 229,
    156, 139, 231, 154, 132, 230, 173, 163, 231, 181, 177, 230,
    128, 167, 239, 188, 140, 231, 149, 182, 229, 156, 168, 228,
    184, 173, 229, 156, 139, 229, 164, 167, 233, 153, 184, 231,
    154, 132, 228, 184, 173, 232, 143, 175, 228, 186, 186, 230,
    176, 145, 229, 133, 177, 229, 146, 140, 229, 156, 139, 230,
    148, 191, 229, 186, 156, 232, 136, 135, 229, 156, 168, 229,
    143, 176, 231, 129, 163, 231, 154, 132, 228, 184, 173, 232,
    143, 175, 230, 176, 145, 229, 156, 139, 230, 148, 191, 229,
    186, 156, 229, 129, 154, 229, 176, 141, 230, 175, 148, 230,
    136, 150, 230, 156, 137, 230, 173, 164, 230, 182, 181, 230,
    140, 135, 230, 153, 130, 239, 188, 140, 229, 137, 141, 232,
    128, 133, 229, 184, 184, 232, 162, 171, 229, 190, 140, 232,
    128, 133, 231, 168, 177, 231, 130, 186, 229, 140, 151, 228,
    186, 172, 231, 149, 182, 229, 177, 128, 227, 128, 129, 229,
    164, 167, 233, 153, 184, 231, 149, 182, 229, 177, 128, 227,
    128, 129, 228, 184, 173, 229, 133, 177, 231, 149, 182, 229,
    177, 128, 227, 128, 129, 228, 184, 173, 229, 156, 139, 229,
    164, 167, 233, 153, 184, 230, 136, 150, 229, 164, 167, 233,
    153, 184, '[', '1', '7', ']', 239, 188, 140, 229, 190, 140,
    232, 128, 133, 229, 184, 184, 232, 162, 171, 229, 137, 141,
    232, 128, 133, 231, 168, 177, 231, 130, 186, 229, 143, 176,
    231, 129, 163, 231, 149, 182, 229, 177, 128, 227, 128, 129,
    229, 143, 176, 229, 140, 151, 231, 149, 182, 229, 177, 128,
    230, 136, 150, 229, 143, 176, 231, 129, 163, '[', '1', '8',
    ']', 227, 128, 130, 232, 136, 135, 230, 184, 175, 230, 190,
    179, 229, 156, 176, 229, 141, 128, 228, 184, 166, 231, 148,
    168, 230, 153, 130, 229, 137, 135, 231, 168, 177, 231, 130,
    186, 228, 184, 173, 229, 156, 139, 229, 133, 167, 229, 156,
    176, 227, 128, 129, 229, 133, 167, 229, 156, 176, '[', '1',
    '9', ']', 227, 128, 130,  13,  10,  13,  10, 231, 149, 182,
    228, 184, 173, 229, 156, 139, 229, 164, 167, 233, 153, 184,
    231, 154, 132, 228, 184, 173, 232, 143, 175, 228, 186, 186,
    230, 176, 145, 229, 133, 177, 229, 146, 140, 229, 156, 139,
    230, 148, 191, 229, 186, 156, 232, 136, 135, 229, 156, 168,
    229, 143, 176, 231, 129, 163, 231, 154, 132, 228, 184, 173,
    232, 143, 175, 230, 176, 145, 229, 156, 139, 230, 148, 191,
    229, 186, 156, 229, 129, 154, 229, 176, 141, 230, 175, 148,
    230, 136, 150, 229, 141, 128, 233, 154, 148, 228, 187, 139,
    231, 180, 185, 230, 153, 130, 239, 188, 140, 233, 128, 154,
    229, 184, 184, 230, 142, 161, 231, 148, 168, 229, 156, 176,
    231, 144, 134, 229, 144, 141, 232, 169, 158, 227, 128, 140,
    228, 184, 173, 229, 156, 139, 229, 164, 167, 233, 153, 184,
    227, 128, 141, 239, 188, 136, 'C', 'h', 'i', 'n', 'a', ' ',
    'M', 'a', 'i', 'n', 'l', 'a', 'n', 'd', 239, 188, 137, 230,
    136, 150, 228, 184, 173, 229, 155, 189, 239, 188, 136, 'C',
    'h', 'i', 'n', 'a', 239, 188, 137, 229, 129, 154, 231, 130,
    186, 228, 184, 173, 232, 143, 175, 228, 186, 186, 230, 176,
    145, 229, 133, 177, 229, 146, 140, 229, 156, 139, 231, 154,
    132, 231, 176, 161, 231, 168, 177, 239, 188, 140, 229, 176,
    141, 230, 150, 188, 228, 184, 173, 232, 143, 175, 230, 176,
    145, 229, 156, 139, 229, 137, 135, 231, 176, 161, 231, 168,
    177, 231, 130, 186, 228, 184, 173, 232, 143, 175, 229, 143,
    176, 229, 140, 151, 239, 188, 136, 'C', 'h', 'i', 'n', 'e',
    's', 'e', ' ', 'T', 'a', 'i', 'p', 'e', 'i', 239, 188, 137,
    230, 136, 150, 229, 143, 176, 231, 129, 163, 239, 188, 136,
    'T', 'a', 'i', 'w', 'a', 'n', 239, 188, 137, 227, 128, 130,
    232, 128, 140, 229, 143, 176, 230, 185, 190, 231, 154, 132,
    229, 170, 146, 228, 189, 147, 229, 137, 135, 229, 184, 184,
    228, 189, 191, 231, 148, 168, 227, 128, 140, 228, 184, 173,
    229, 133, 177, 227, 128, 141, 227, 128, 129, 227, 128, 140,
    229, 164, 167, 233, 153, 184, 229, 156, 176, 229, 141, 128,
    227, 128, 141, 227, 128, 129, 227, 128, 140, 229, 164, 167,
    233, 153, 184, 227, 128, 141, 230, 136, 150, 227, 128, 140,
    228, 184, 173, 229, 155, 189, 227, 128, 141, 230, 157, 165,
    228, 189, 156, 231, 130, 186, 228, 184, 173, 232, 143, 175,
    228, 186, 186, 230, 176, 145, 229, 133, 177, 229, 146, 140,
    229, 156, 139, 231, 154, 132, 231, 176, 161, 231, 168, 177,
    227, 128, 130, 233, 166, 153, 230, 184, 175, 233, 131, 168,
    229, 136, 134, 229, 170, 146, 233, 171, 148, 228, 185, 159,
    230, 156, 137, 228, 189, 191, 231, 148, 168, 227, 128, 140,
    228, 184, 173, 229, 156, 139, 227, 128, 141, 229, 146, 140,
    227, 128, 140, 228, 184, 173, 229, 133, 177, 227, 128, 141,
    228, 190, 134, 230, 140, 135, 228, 187, 163, 228, 184, 173,
    229, 156, 139, 229, 164, 167, 233, 153, 184, 227, 128, 130,
     13,  10,  13,  10, '1', '9', '4', '9', 229, 185, 180, 239,
    188, 140, 230, 173, 183, 230, 153, 130, 228, 184, 137, 229,
    185, 180, 231, 154, 132, 229, 156, 139, 229, 133, 177, 229,
    133, 167, 230, 136, 176, 228, 184, 187, 232, 166, 129, 230,
    136, 176, 229, 189, 185, 231, 181, 144, 230, 157, 159, 239,
    188, 140, 228, 184, 173, 229, 156, 139, 229, 133, 177, 231,
    148, 162, 233, 187, 168, 230, 137, 128, 233, 160, 152, 229,
    176, 142, 231, 154, 132, 228, 184, 173, 229, 156, 139, 228,
    186, 186, 230, 176, 145, 232, 167, 163, 230, 148, 190, 232,
    187, 141, 230, 136, 176, 229, 139, 157, 228, 186, 134, 228,
    184, 173, 229, 156, 139, 229, 156, 139, 230, 176, 145, 233,
    187, 168, 230, 137, 128, 233, 160, 152, 229, 176, 142, 231,
    154, 132, 228, 184, 173, 232, 143, 175, 230, 176, 145, 229,
    156, 139, 229, 155, 189, 232, 187, 141, '[', 230, 179, 168,
    ' ', '6', ']', 239, 188, 140, 228, 184, 166, 229, 183, 178,
    233, 128, 144, 230, 188, 184, 230, 142, 167, 229, 136, 182,
    228, 186, 134, 228, 184, 173, 229, 156, 139, 229, 164, 167,
    233, 153, 184, 229, 164, 167, 233, 131, 168, 229, 136, 134,
    231, 156, 129, 228, 187, 189, 229, 146, 140, 229, 156, 176,
    229, 140, 186, 227, 128, 130,  13,  10,  13,  10, 229, 144,
    140, 229, 185, 180, '9', 230, 156, 136, '2', '1', 230, 151,
    165, 232, 135, 179, '9', 230, 156, 136, '3', '0', 230, 151,
    165, 239, 188, 140, 231, 182, 147, 233, 129, 142, 230, 149,
    184, 230, 156, 136, 231, 154, 132, 231, 177, 140, 229, 130,
    153, 239, 188, 140, 228, 184, 173, 229, 156, 139, 228, 186,
    186, 230, 176, 145, 230, 148, 191, 230, 178, 187, 229, 141,
    148, 229, 149, 134, 230, 156, 131, 232, 173, 176, 231, 172,
    172, 228, 184, 128, 229, 177, 134, 229, 133, 168, 233, 171,
    148, 230, 156, 131, 232, 173, 176, 229, 156, 168, 229, 140,
    151, 229, 185, 179, 229, 143, 172, 233, 150, 139, 227, 128,
    130, '9', 230, 156, 136, '2', '1', 230, 151, 165, 239, 188,
    140, 228, 184, 173, 229, 156, 139, 228, 186, 186, 230, 176,
    145, 230, 148, 191, 230, 178, 187, 229, 141, 148, 229, 149,
    134, 230, 156, 131, 232, 173, 176, 231, 172, 172, 228, 184,
    128, 229, 177, 134, 229, 133, 168, 233, 171, 148, 230, 156,
    131, 232, 173, 176, 230, 173, 163, 229, 188, 143, 229, 174,
    163, 229, 184, 131, 230, 136, 144, 231, 171, 139, 228, 184,
    173, 229, 141, 142, 228, 186, 186, 230, 176, 145, 229, 133,
    177, 229, 146, 140, 229, 155, 189, '[', '2', '0', ']', 227,
    128, 130, 228, 188, 154, 232, 174, 174, 233, 128, 154, 233,
    129, 142, 228, 186, 134, 227, 128, 138, 228, 184, 173, 229,
    156, 139, 228, 186, 186, 230, 176, 145, 230, 148, 191, 230,
    178, 187, 229, 141, 148, 229, 149, 134, 230, 156, 131, 232,
    173, 176, 231, 181, 132, 231, 185, 148, 230, 179, 149, 227,
    128, 139, 227, 128, 129, 227, 128, 138, 228, 184, 173, 232,
    143, 175, 228, 186, 186, 230, 176, 145, 229, 133, 177, 229,
    146, 140, 229, 156, 139, 228, 184, 173, 229, 164, 174, 228,
    186, 186, 230, 176, 145, 230, 148, 191, 229, 186, 156, 231,
    181, 132, 231, 185, 148, 230, 179, 149, 227, 128, 139, 229,
    146, 140, 229, 133, 183, 230, 156, 137, 232, 135, 168, 230,
    153, 130, 230, 134, 178, 230, 179, 149, 230, 128, 167, 232,
    179, 170, 231, 154, 132, 227, 128, 138, 228, 184, 173, 229,
    156, 139, 228, 186, 186, 230, 176, 145, 230, 148, 191, 230,
    178, 187, 229, 141, 148, 229, 149, 134, 230, 156, 131, 232,
    173, 176, 229, 133, 177, 229, 144, 140, 231, 182, 177, 233,
    160, 152, 227, 128, 139, 239, 188, 140, 230, 177, 186, 229,
    174, 154, 228, 187, 165, 229, 140, 151, 229, 185, 179, 231,
    130, 186, 233, 166, 150, 233, 131, 189, 228, 184, 166, 230,
    148, 185, 229, 144, 141, 231, 136, 178, 229, 140, 151, 228,
    186, 172, 227, 128, 129, 228, 187, 165, 229, 133, 172, 229,
    133, 131, 231, 180, 128, 229, 185, 180, 227, 128, 129, 228,
    187, 165, 231, 190, 169, 229, 139, 135, 232, 187, 141, 233,
    128, 178, 232, 161, 140, 230, 155, 178, 231, 130, 186, 228,
    187, 163, 229, 156, 139, 230, 173, 140, 227, 128, 129, 228,
    187, 165, 228, 186, 148, 230, 152, 159, 231, 180, 133, 230,
    151, 151, 231, 130, 186, 229, 156, 139, 230, 151, 151, 239,
    188, 140, 233, 128, 154, 233, 129, 142, 228, 186, 134, 231,
    148, 177, '1', '8', '0', 228, 186, 186, 231, 181, 132, 230,
    136, 144, 231, 154, 132, 228, 184, 173, 229, 156, 139, 228,
    186, 186, 230, 176, 145, 230, 148, 191, 230, 178, 187, 229,
    141, 148, 229, 149, 134, 230, 156, 131, 232, 173, 176, 231,
    172, 172, 228, 184, 128, 229, 177, 134, 229, 133, 168, 229,
    156, 139, 229, 167, 148, 229, 147, 161, 230, 156, 131, 229,
    144, 141, 229, 150, 174, 239, 188, 140, 228, 184, 166, 233,
    129, 184, 232, 136, 137, 230, 175, 155, 230, 190, 164, 230,
    157, 177, 231, 130, 186, 228, 184, 173, 229, 164, 174, 228,
    186, 186, 230, 176, 145, 230, 148, 191, 229, 186, 156, 228,
    184, 187, 229, 184, 173, 227, 128, 129, 230, 156, 177, 229,
    190, 183, 227, 128, 129, 229, 136, 152, 229, 176, 145, 229,
    165, 135, 227, 128, 129, 229, 174, 139, 229, 186, 134, 233,
    190, 132, 227, 128, 129, 230, 157, 142, 230, 181, 142, 230,
    183, 177, 227, 128, 129, 229, 188, 160, 230, 190, 156, 227,
    128, 129, 233, 171, 152, 229, 178, 151, 231, 130, 186, 229,
    137, 175, 228, 184, 187, 229, 184, 173, 227, 128, 129, 229,
    143, 166, 229, 164, 150, '5', '6', 228, 189, 141, 231, 130,
    186, 228, 184, 173, 229, 164, 174, 228, 186, 186, 230, 176,
    145, 230, 148, 191, 229, 186, 156, 229, 167, 148, 229, 147,
    161, 227, 128, 130, '1', '0', 230, 156, 136, '1', 230, 151,
    165, 229, 188, 128, 229, 155, 189, 229, 164, 167, 229, 133,
    184, 229, 156, 168, 229, 140, 151, 228, 186, 172, 228, 184,
    190, 232, 161, 140, 239, 188, 140, 230, 175, 155, 230, 190,
    164, 230, 157, 177, 229, 156, 168, 229, 164, 169, 229, 174,
    137, 233, 151, 168, 229, 159, 142, 230, 165, 188, 229, 174,
    163, 229, 145, 138, 228, 184, 173, 229, 141, 142, 228, 186,
    186, 230, 176, 145, 229, 133, 177, 229, 146, 140, 229, 155,
    189, 228, 184, 173, 229, 164, 174, 228, 186, 186, 230, 176,
    145, 230, 148, 191, 229, 186, 156, 230, 136, 144, 231, 171,
    139, 239, 188, 155, '1', '2', 230, 156, 136, '7', 230, 151,
    165, 239, 188, 140, 228, 184, 173, 232, 143, 175, 230, 176,
    145, 229, 156, 139, 230, 148, 191, 229, 186, 156, 230, 173,
    163, 229, 188, 143, 231, 148, 177, 229, 155, 155, 229, 183,
    157, 231, 156, 129, 230, 136, 144, 233, 131, 189, 229, 184,
    130, 233, 129, 183, 229, 190, 128, 229, 143, 176, 230, 185,
    190, 231, 156, 129, 229, 143, 176, 229, 140, 151, 229, 184,
    130, 239, 188, 140, 228, 184, 166, 231, 185, 188, 231, 186,
    140, 231, 181, 177, 230, 178, 187, 229, 143, 176, 231, 129,
    163, 230, 156, 172, 229, 179, 182, 229, 143, 138, 230, 190,
    142, 230, 185, 150, 227, 128, 129, 233, 131, 168, 229, 136,
    134, 231, 166, 143, 229, 187, 186, 233, 155, 162, 229, 179,
    182, 227, 128, 129, 228, 184, 156, 230, 178, 153, 231, 190,
    164, 229, 178, 155, 227, 128, 129, 229, 164, 170, 229, 185,
    179, 229, 178, 155, 231, 173, 137, 232, 135, 179, 228, 187,
    138, 227, 128, 130, 232, 135, 179, 230, 173, 164, 239, 188,
    140, 228, 184, 173, 229, 156, 139, 230, 173, 183, 229, 143,
    178, 228, 184, 138, 230, 150, 188, 230, 181, 183, 229, 179,
    189, 229, 133, 169, 229, 178, 184, 229, 136, 134, 230, 178,
    187, 231, 154, 132, 230, 148, 191, 230, 178, 187, 230, 160,
    188, 229, 177, 128, 230, 173, 163, 229, 188, 143, 229, 189,
    162, 230, 136, 144, 227, 128, 130,  13,  10,  13,  10, 'H',
    'i', 'n', 'd', 'i', ':',  13,  10,  13,  10, 224, 164, 173,
    224, 164, 190, 224, 164, 176, 224, 164, 164, ',', ' ', 224,
    164, 170, 224, 165, 140, 224, 164, 176, 224, 164, 190, 224,
    164, 163, 224, 164, 191, 224, 164, 149, ' ', 224, 164, 156,
    224, 164, 174, 224, 165, 141, 224, 164, 172, 224, 165, 130,
    224, 164, 166, 224, 165, 141, 224, 164, 181, 224, 165, 128,
    224, 164, 170, ',', ' ', 224, 164, 134, 224, 164, 167, 224,
    165, 129, 224, 164, 168, 224, 164, 191, 224, 164, 149, ' ',
    224, 164, 166, 224, 164, 149, 224, 165, 141, 224, 164, 183,
    224, 164, 191, 224, 164, 163, ' ', 224, 164, 143, 224, 164,
    182, 224, 164, 191, 224, 164, 175, 224, 164, 190, ' ', 224,
    164, 174, 224, 165, 135, 224, 164, 130, ' ', 224, 164, 184,
    224, 165, 141, 224, 164, 165, 224, 164, 191, 224, 164, 164,
    ' ', 224, 164, 173, 224, 164, 190, 224, 164, 176, 224, 164,
    164, 224, 165, 128, 224, 164, 175, ' ', 224, 164, 137, 224,
    164, 170, 224, 164, 174, 224, 164, 185, 224, 164, 190, 224,
    164, 166, 224, 165, 141, 224, 164, 181, 224, 165, 128, 224,
    164, 170, ' ', 224, 164, 149, 224, 164, 190, ' ', 224, 164,
    184, 224, 164, 172, 224, 164, 184, 224, 165, 135, ' ', 224,
    164, 172, 224, 164, 161, 224, 164, 188, 224, 164, 190, ' ',
    224, 164, 166, 224, 165, 135, 224, 164, 182, ' ', 224, 164,
    185, 224, 165, 136, 224, 165, 164, ' ', 224, 164, 173, 224,
    164, 190, 224, 164, 176, 224, 164, 164, ' ', 224, 164, 149,
    224, 164, 190, ' ', 224, 164, 173, 224, 165, 140, 224, 164,
    151, 224, 165, 139, 224, 164, 178, 224, 164, 191, 224, 164,
    149, ' ', 224, 164, 171, 224, 165, 136, 224, 164, 178, 224,
    164, 190, 224, 164, 181, ' ', 224, 165, 174, 224, 165, 166,
    ' ', 224, 165, 170,'\'', ' ', 224, 164, 184, 224, 165, 135,
    ' ', 224, 165, 169, 224, 165, 173, 224, 165, 166, ' ', 224,
    165, 172,'\'', ' ', 224, 164, 137, 224, 164, 164, 224, 165,
    141, 224, 164, 164, 224, 164, 176, 224, 165, 128, ' ', 224,
    164, 133, 224, 164, 149, 224, 165, 141, 224, 164, 183, 224,
    164, 190, 224, 164, 130, 224, 164, 182, ' ', 224, 164, 164,
    224, 164, 149, ' ', 224, 164, 164, 224, 164, 165, 224, 164,
    190, ' ', 224, 165, 172, 224, 165, 174, 224, 165, 166, ' ',
    224, 165, 173,'\'', ' ', 224, 164, 184, 224, 165, 135, ' ',
    224, 165, 175, 224, 165, 173, 224, 165, 166, ' ', 224, 165,
    168, 224, 165, 171,'\'', 224, 164, 170, 224, 165, 130, 224,
    164, 176, 224, 165, 141, 224, 164, 181, 224, 165, 128, ' ',
    224, 164, 166, 224, 165, 135, 224, 164, 182, 224, 164, 190,
    224, 164, 168, 224, 165, 141, 224, 164, 164, 224, 164, 176,
    ' ', 224, 164, 164, 224, 164, 149, ' ', 224, 164, 185, 224,
    165, 136, 224, 165, 164, ' ', 224, 164, 173, 224, 164, 190,
    224, 164, 176, 224, 164, 164, ' ', 224, 164, 149, 224, 164,
    190, ' ', 224, 164, 181, 224, 164, 191, 224, 164, 184, 224,
    165, 141, 224, 164, 164, 224, 164, 190, 224, 164, 176, ' ',
    224, 164, 137, 224, 164, 164, 224, 165, 141, 224, 164, 164,
    224, 164, 176, ' ', 224, 164, 184, 224, 165, 135, ' ', 224,
    164, 166, 224, 164, 149, 224, 165, 141, 224, 164, 183, 224,
    164, 191, 224, 164, 163, ' ', 224, 164, 164, 224, 164, 149,
    ' ', 224, 164, 149, 224, 164, 191, '.', ' ', 224, 164, 174,
    224, 165, 128, '.', ' ', 224, 164, 148, 224, 164, 176, ' ',
    224, 164, 170, 224, 165, 130, 224, 164, 176, 224, 165, 141,
    224, 164, 181, ' ', 224, 164, 184, 224, 165, 135, ' ', 224,
    164, 170, 224, 164, 182, 224, 165, 141, 224, 164, 154, 224,
    164, 191, 224, 164, 174, ' ', 224, 164, 164, 224, 164, 149,
    ' ', 224, 165, 168, ',', 224, 165, 175, 224, 165, 169, 224,
    165, 169, ' ', 224, 164, 149, 224, 164, 191, '.', ' ', 224,
    164, 174, 224, 165, 128, '.', ' ', 224, 164, 185, 224, 165,
    136, 224, 165, 164, ' ', 224, 164, 173, 224, 164, 190, 224,
    164, 176, 224, 164, 164, ' ', 224, 164, 149, 224, 165, 128,
    ' ', 224, 164, 184, 224, 164, 174, 224, 165, 129, 224, 164,
    166, 224, 165, 141, 224, 164, 176, ' ', 224, 164, 164, 224,
    164, 159, ' ', 224, 164, 176, 224, 165, 135, 224, 164, 150,
    224, 164, 190, ' ', 224, 165, 173, 224, 165, 171, 224, 165,
    167, 224, 165, 172, '.', 224, 165, 172, ' ', 224, 164, 149,
    224, 164, 191, 224, 164, 178, 224, 165, 139, 224, 164, 174,
    224, 165, 128, 224, 164, 159, 224, 164, 176, ' ', 224, 164,
    178, 224, 164, 174, 224, 165, 141, 224, 164, 172, 224, 165,
    128, ' ', 224, 164, 185, 224, 165, 136, 224, 165, 164, ' ',
    224, 164, 173, 224, 164, 190, 224, 164, 176, 224, 164, 164,
    ',', ' ', 224, 164, 173, 224, 165, 140, 224, 164, 151, 224,
    165, 139, 224, 164, 178, 224, 164, 191, 224, 164, 149, ' ',
    224, 164, 166, 224, 165, 131, 224, 164, 183, 224, 165, 141,
    224, 164, 159, 224, 164, 191, ' ', 224, 164, 184, 224, 165,
    135, ' ', 224, 164, 181, 224, 164, 191, 224, 164, 182, 224,
    165, 141, 224, 164, 181, ' ', 224, 164, 174, 224, 165, 135,
    224, 164, 130, ' ', 224, 164, 184, 224, 164, 190, 224, 164,
    164, 224, 164, 181, 224, 164, 190, 224, 164, 129, ' ', 224,
    164, 184, 224, 164, 172, 224, 164, 184, 224, 165, 135, ' ',
    224, 164, 172, 224, 164, 161, 224, 164, 188, 224, 164, 190,
    ' ', 224, 164, 148, 224, 164, 176, ' ', 224, 164, 156, 224,
    164, 168, 224, 164, 184, 224, 164, 129, 224, 164, 150, 224,
    165, 141, 224, 164, 175, 224, 164, 190, ' ', 224, 164, 149,
    224, 165, 135, ' ', 224, 164, 166, 224, 165, 131, 224, 164,
    183, 224, 165, 141, 224, 164, 159, 224, 164, 191, 224, 164,
    149, 224, 165, 139, 224, 164, 163, ' ', 224, 164, 184, 224,
    165, 135, ' ', 224, 164, 166, 224, 165, 130, 224, 164, 184,
    224, 164, 176, 224, 164, 190, ' ', 224, 164, 184, 224, 164,
    172, ' ', 224, 164, 184, 224, 165, 135, ' ', 224, 164, 172,
    224, 164, 161, 224, 164, 188, 224, 164, 190, ' ', 224, 164,
    166, 224, 165, 135, 224, 164, 182, ' ', 224, 164, 185, 224,
    165, 136, 224, 165, 164, ' ', 224, 164, 173, 224, 164, 190,
    224, 164, 176, 224, 164, 164, ' ', 224, 164, 149, 224, 165,
    135, ' ', 224, 164, 170, 224, 164, 182, 224, 165, 141, 224,
    164, 154, 224, 164, 191, 224, 164, 174, ' ', 224, 164, 174,
    224, 165, 135, 224, 164, 130, ' ', 224, 164, 170, 224, 164,
    190, 224, 164, 149, 224, 164, 191, 224, 164, 184, 224, 165,
    141, 224, 164, 164, 224, 164, 190, 224, 164, 168, ',', ' ',
    224, 164, 137, 224, 164, 164, 224, 165, 141, 224, 164, 164,
    224, 164, 176, '-', 224, 164, 170, 224, 165, 130, 224, 164,
    176, 224, 165, 141, 224, 164, 181, ' ', 224, 164, 174, 224,
    165, 135, 224, 164, 130, ' ', 224, 164, 154, 224, 165, 128,
    224, 164, 168, ',', ' ', 224, 164, 168, 224, 165, 135, 224,
    164, 170, 224, 164, 190, 224, 164, 178, ',', ' ', 224, 164,
    148, 224, 164, 176, ' ', 224, 164, 173, 224, 165, 130, 224,
    164, 159, 224, 164, 190, 224, 164, 168, ' ', 224, 164, 148,
    224, 164, 176, ' ', 224, 164, 170, 224, 165, 130, 224, 164,
    176, 224, 165, 141, 224, 164, 181, ' ', 224, 164, 174, 224,
    165, 135, 224, 164, 130, ' ', 224, 164, 172, 224, 164, 190,
    224, 164, 130, 224, 164, 151, 224, 165, 141, 224, 164, 178,
    224, 164, 190, 224, 164, 166, 224, 165, 135, 224, 164, 182,
    ' ', 224, 164, 148, 224, 164, 176, ' ', 224, 164, 174, 224,
    165, 141, 224, 164, 175, 224, 164, 190, 224, 164, 168, 224,
    165, 141, 224, 164, 174, 224, 164, 190, 224, 164, 176, ' ',
    224, 164, 166, 224, 165, 135, 224, 164, 182, ' ', 224, 164,
    184, 224, 165, 141, 224, 164, 165, 224, 164, 191, 224, 164,
    164, ' ', 224, 164, 185, 224, 165, 136, 224, 164, 130, 224,
    165, 164, ' ', 224, 164, 185, 224, 164, 191, 224, 164, 168,
    224, 165, 141, 224, 164, 166, ' ', 224, 164, 174, 224, 164,
    185, 224, 164, 190, 224, 164, 184, 224, 164, 190, 224, 164,
    151, 224, 164, 176, ' ', 224, 164, 174, 224, 165, 135, 224,
    164, 130, ' ', 224, 164, 135, 224, 164, 184, 224, 164, 149,
    224, 165, 135, ' ', 224, 164, 166, 224, 164, 149, 224, 165,
    141, 224, 164, 183, 224, 164, 191, 224, 164, 163, ' ', 224,
    164, 170, 224, 164, 182, 224, 165, 141, 224, 164, 154, 224,
    164, 191, 224, 164, 174, ' ', 224, 164, 174, 224, 165, 135,
    224, 164, 130, ' ', 224, 164, 174, 224, 164, 190, 224, 164,
    178, 224, 164, 166, 224, 165, 128, 224, 164, 181, ',', ' ',
    224, 164, 166, 224, 164, 149, 224, 165, 141, 224, 164, 183,
    224, 164, 191, 224, 164, 163, ' ', 224, 164, 174, 224, 165,
    135, 224, 164, 130, ' ', 224, 164, 182, 224, 165, 141, 224,
    164, 176, 224, 165, 128, 224, 164, 178, 224, 164, 130, 224,
    164, 149, 224, 164, 190, ' ', 224, 164, 148, 224, 164, 176,
    ' ', 224, 164, 166, 224, 164, 149, 224, 165, 141, 224, 164,
    183, 224, 164, 191, 224, 164, 163, '-', 224, 164, 170, 224,
    165, 130, 224, 164, 176, 224, 165, 141, 224, 164, 181, ' ',
    224, 164, 174, 224, 165, 135, 224, 164, 130, ' ', 224, 164,
    135, 224, 164, 130, 224, 164, 161, 224, 165, 139, 224, 164,
    168, 224, 165, 135, 224, 164, 182, 224, 164, 191, 224, 164,
    175, 224, 164, 190, ' ', 224, 164, 185, 224, 165, 136, 224,
    164, 130, 224, 165, 164, ' ', 224, 164, 137, 224, 164, 164,
    224, 165, 141, 224, 164, 164, 224, 164, 176, '-', 224, 164,
    170, 224, 164, 182, 224, 165, 141, 224, 164, 154, 224, 164,
    191, 224, 164, 174, ' ', 224, 164, 174, 224, 165, 135, 224,
    164, 130, ' ', 224, 164, 133, 224, 164, 171, 224, 164, 188,
    224, 164, 151, 224, 164, 190, 224, 164, 168, 224, 164, 191,
    224, 164, 184, 224, 165, 141, 224, 164, 164, 224, 164, 190,
    224, 164, 168, ' ', 224, 164, 149, 224, 165, 135, ' ', 224,
    164, 184, 224, 164, 190, 224, 164, 165, ' ', 224, 164, 173,
    224, 164, 190, 224, 164, 176, 224, 164, 164, ' ', 224, 164,
    149, 224, 165, 128, ' ', 224, 164, 184, 224, 165, 128, 224,
    164, 174, 224, 164, 190, ' ', 224, 164, 185, 224, 165, 136,
    224, 165, 164, ' ', 224, 164, 135, 224, 164, 184, 224, 164,
    149, 224, 165, 135, ' ', 224, 164, 137, 224, 164, 164, 224,
    165, 141, 224, 164, 164, 224, 164, 176, ' ', 224, 164, 174,
    224, 165, 135, 224, 164, 130, ' ', 224, 164, 185, 224, 164,
    191, 224, 164, 174, 224, 164, 190, 224, 164, 178, 224, 164,
    175, ' ', 224, 164, 170, 224, 164, 176, 224, 165, 141, 224,
    164, 181, 224, 164, 164, ' ', 224, 164, 185, 224, 165, 136,
    ' ', 224, 164, 148, 224, 164, 176, ' ', 224, 164, 166, 224,
    164, 149, 224, 165, 141, 224, 164, 183, 224, 164, 191, 224,
    164, 163, ' ', 224, 164, 174, 224, 165, 135, 224, 164, 130,
    ' ', 224, 164, 185, 224, 164, 191, 224, 164, 168, 224, 165,
    141, 224, 164, 166, ' ', 224, 164, 174, 224, 164, 185, 224,
    164, 190, 224, 164, 184, 224, 164, 190, 224, 164, 151, 224,
    164, 176, ' ', 224, 164, 185, 224, 165, 136, 224, 165, 164,
    ' ', 224, 164, 170, 224, 165, 130, 224, 164, 176, 224, 165,
    141, 224, 164, 181, ' ', 224, 164, 174, 224, 165, 135, 224,
    164, 130, ' ', 224, 164, 172, 224, 164, 130, 224, 164, 151,
    224, 164, 190, 224, 164, 178, ' ', 224, 164, 149, 224, 165,
    128, ' ', 224, 164, 150, 224, 164, 190, 224, 164, 161, 224,
    164, 188, 224, 165, 128, ' ', 224, 164, 185, 224, 165, 136,
    ' ', 224, 164, 164, 224, 164, 165, 224, 164, 190, ' ', 224,
    164, 170, 224, 164, 182, 224, 165, 141, 224, 164, 154, 224,
    164, 191, 224, 164, 174, ' ', 224, 164, 174, 224, 165, 135,
    224, 164, 130, ' ', 224, 164, 133, 224, 164, 176, 224, 164,
    172, ' ', 224, 164, 184, 224, 164, 190, 224, 164, 151, 224,
    164, 176, 224, 164, 184, 224, 164, 174, 224, 165, 129, 224,
    164, 166, 224, 165, 141, 224, 164, 176, ' ', 224, 164, 185,
    224, 165, 136, 224, 164, 130, ' ', 224, 165, 164, ' ', 224,
    164, 173, 224, 164, 190, 224, 164, 176, 224, 164, 164, ' ',
    224, 164, 174, 224, 165, 135, 224, 164, 130, ' ', 224, 164,
    149, 224, 164, 136, ' ', 224, 164, 172, 224, 164, 161, 224,
    164, 188, 224, 165, 128, ' ', 224, 164, 168, 224, 164, 166,
    224, 164, 191, 224, 164, 175, 224, 164, 190, 224, 164, 129,
    ' ', 224, 164, 185, 224, 165, 136, 224, 164, 130, ' ', 224,
    165, 164, ' ', 224, 164, 151, 224, 164, 130, 224, 164, 151,
    224, 164, 190, ' ', 224, 164, 168, 224, 164, 166, 224, 165,
    128, ' ', 224, 164, 173, 224, 164, 190, 224, 164, 176, 224,
    164, 164, 224, 165, 128, 224, 164, 175, ' ', 224, 164, 184,
    224, 164, 130, 224, 164, 184, 224, 165, 141, 224, 164, 149,
    224, 165, 131, 224, 164, 164, 224, 164, 191, ' ', 224, 164,
    174, 224, 165, 135, 224, 164, 130, ' ', 224, 164, 133, 224,
    164, 164, 224, 165, 141, 224, 164, 175, 224, 164, 130, 224,
    164, 164, ' ', 224, 164, 170, 224, 164, 181, 224, 164, 191,
    224, 164, 164, 224, 165, 141, 224, 164, 176, ' ', 224, 164,
    174, 224, 164, 190, 224, 164, 168, 224, 165, 128, ' ', 224,
    164, 156, 224, 164, 190, 224, 164, 164, 224, 165, 128, ' ',
    224, 164, 185, 224, 165, 136, 224, 165, 164, ' ', 224, 164,
    133, 224, 164, 168, 224, 165, 141, 224, 164, 175, ' ', 224,
    164, 172, 224, 164, 161, 224, 164, 188, 224, 165, 128, ' ',
    224, 164, 168, 224, 164, 166, 224, 164, 191, 224, 164, 175,
    224, 164, 190, 224, 164, 129, ' ', 224, 164, 184, 224, 164,
    191, 224, 164, 168, 224, 165, 141, 224, 164, 167, 224, 165,
    129, ',', ' ', 224, 164, 168, 224, 164, 176, 224, 165, 141,
    224, 164, 174, 224, 164, 166, 224, 164, 190, ',', ' ', 224,
    164, 172, 224, 165, 141, 224, 164, 176, 224, 164, 185, 224,
    165, 141, 224, 164, 174, 224, 164, 170, 224, 165, 129, 224,
    164, 164, 224, 165, 141, 224, 164, 176, ',', ' ', 224, 164,
    175, 224, 164, 174, 224, 165, 129, 224, 164, 168, 224, 164,
    190, ',', ' ', 224, 164, 151, 224, 165, 139, 224, 164, 166,
    224, 164, 190, 224, 164, 181, 224, 164, 176, 224, 165, 128,
    ',', ' ', 224, 164, 149, 224, 164, 190, 224, 164, 181, 224,
    165, 135, 224, 164, 176, 224, 165, 128, ',', ' ', 224, 164,
    149, 224, 165, 131, 224, 164, 183, 224, 165, 141, 224, 164,
    163, 224, 164, 190, ',', ' ', 224, 164, 154, 224, 164, 174,
    224, 165, 141, 224, 164, 172, 224, 164, 178, ',', ' ', 224,
    164, 184, 224, 164, 164, 224, 164, 178, 224, 164, 156, ',',
    ' ', 224, 164, 181, 224, 165, 141, 224, 164, 175, 224, 164,
    190, 224, 164, 184, ' ', 224, 164, 134, 224, 164, 166, 224,
    164, 191, ' ', 224, 164, 185, 224, 165, 136, 224, 164, 130,
    224, 165, 164,  13,  10,  13,  10, 224, 164, 175, 224, 164,
    185, ' ', 224, 164, 181, 224, 164, 191, 224, 164, 182, 224,
    165, 141, 224, 164, 181, ' ', 224, 164, 149, 224, 164, 190,
    ' ', 224, 164, 184, 224, 164, 172, 224, 164, 184, 224, 165,
    135, ' ', 224, 164, 172, 224, 164, 161, 224, 164, 188, 224,
    164, 190, ' ', 224, 164, 178, 224, 165, 139, 224, 164, 149,
    224, 164, 164, 224, 164, 130, 224, 164, 164, 224, 165, 141,
    224, 164, 176, ' ', 224, 164, 185, 224, 165, 136, 224, 165,
    164, ' ', 224, 164, 175, 224, 164, 185, 224, 164, 190, 224,
    164, 129, ' ', 224, 165, 169, 224, 165, 166, 224, 165, 166,
    ' ', 224, 164, 184, 224, 165, 135, ' ', 224, 164, 133, 224,
    164, 167, 224, 164, 191, 224, 164, 149, ' ', 224, 164, 173,
    224, 164, 190, 224, 164, 183, 224, 164, 190, 224, 164, 143,
    224, 164, 129, ' ', 224, 164, 172, 224, 165, 139, 224, 164,
    178, 224, 165, 128, ' ', 224, 164, 156, 224, 164, 190, 224,
    164, 164, 224, 165, 128, ' ', 224, 164, 185, 224, 165, 136,
    224, 164, 130, ' ', '[', '1', ']', 224, 165, 164, ' ', 224,
    164, 175, 224, 164, 185, ' ', 224, 164, 181, 224, 164, 191,
    224, 164, 182, 224, 165, 141, 224, 164, 181, ' ', 224, 164,
    149, 224, 165, 128, ' ', 224, 164, 149, 224, 165, 129, 224,
    164, 155, ' ', 224, 164, 170, 224, 165, 141, 224, 164, 176,
    224, 164, 190, 224, 164, 154, 224, 165, 128, 224, 164, 168,
    224, 164, 164, 224, 164, 174, ' ', 224, 164, 184, 224, 164,
    173, 224, 165, 141, 224, 164, 175, 224, 164, 164, 224, 164,
    190, 224, 164, 147, 224, 164, 130, ' ', 224, 164, 149, 224,
    165, 128, ' ', 224, 164, 156, 224, 164, 168, 224, 164, 168,
    224, 165, 128, ' ', 224, 164, 176, 224, 164, 185, 224, 164,
    190, ' ', 224, 164, 185, 224, 165, 136, ' ', 224, 164, 156,
    224, 165, 136, 224, 164, 184, 224, 165, 135, ' ', '-', ' ',
    224, 164, 184, 224, 164, 191, 224, 164, 168, 224, 165, 141,
    224, 164, 167, 224, 165, 129, ' ', 224, 164, 152, 224, 164,
    190, 224, 164, 159, 224, 165, 128, ' ', 224, 164, 184, 224,
    164, 173, 224, 165, 141, 224, 164, 175, 224, 164, 164, 224,
    164, 190, ',', ' ', 224, 164, 148, 224, 164, 176, ' ', 224,
    164, 174, 224, 164, 185, 224, 164, 164, 224, 165, 141, 224,
    164, 181, 224, 164, 170, 224, 165, 130, 224, 164, 176, 224,
    165, 141, 224, 164, 163, ' ', 224, 164, 144, 224, 164, 164,
    224, 164, 191, 224, 164, 185, 224, 164, 190, 224, 164, 184,
    224, 164, 191, 224, 164, 149, ' ', 224, 164, 181, 224, 165,
    141, 224, 164, 175, 224, 164, 190, 224, 164, 170, 224, 164,
    190, 224, 164, 176, ' ', 224, 164, 170, 224, 164, 165, 224,
    165, 139, 224, 164, 130, ' ', 224, 164, 149, 224, 164, 190,
    ' ', 224, 164, 133, 224, 164, 173, 224, 164, 191, 224, 164,
    168, 224, 165, 141, 224, 164, 168, ' ', 224, 164, 133, 224,
    164, 130, 224, 164, 151, ' ', 224, 164, 173, 224, 165, 128,
    '.', ' ', 224, 164, 181, 224, 164, 191, 224, 164, 182, 224,
    165, 141, 224, 164, 181, ' ', 224, 164, 149, 224, 165, 135,
    ' ', 224, 164, 154, 224, 164, 190, 224, 164, 176, ' ', 224,
    164, 170, 224, 165, 141, 224, 164, 176, 224, 164, 174, 224,
    165, 129, 224, 164, 150, ' ', 224, 164, 167, 224, 164, 176,
    224, 165, 141, 224, 164, 174, ' ', ':', ' ', 224, 164, 184,
    224, 164, 168, 224, 164, 190, 224, 164, 164, 224, 164, 168,
    '-', 224, 164, 185, 224, 164, 191, 224, 164, 168, 224, 165,
    141, 224, 164, 166, 224, 165, 130, ',', ' ', 224, 164, 172,
    224, 165, 140, 224, 164, 166, 224, 165, 141, 224, 164, 167,
    ',', ' ', 224, 164, 156, 224, 165, 136, 224, 164, 168, ' ',
    224, 164, 164, 224, 164, 165, 224, 164, 190, ' ', 224, 164,
    184, 224, 164, 191, 224, 164, 150, ' ', 224, 164, 173, 224,
    164, 190, 224, 164, 176, 224, 164, 164, ' ', 224, 164, 174,
    224, 165, 135, 224, 164, 130, ' ', 224, 164, 185, 224, 165,
    128, ' ', 224, 164, 156, 224, 164, 168, 224, 165, 141, 224,
    164, 174, 224, 165, 135, ' ', 224, 164, 148, 224, 164, 176,
    ' ', 224, 164, 181, 224, 164, 191, 224, 164, 149, 224, 164,
    184, 224, 164, 191, 224, 164, 164, ' ', 224, 164, 185, 224,
    165, 129, 224, 164, 143, 224, 165, 164,  13,  10,  13,  10,
    224, 164, 173, 224, 164, 190, 224, 164, 176, 224, 164, 164,
    ' ', 224, 164, 173, 224, 165, 140, 224, 164, 151, 224, 165,
    139, 224, 164, 178, 224, 164, 191, 224, 164, 149, ' ', 224,
    164, 149, 224, 165, 141, 224, 164, 183, 224, 165, 135, 224,
    164, 164, 224, 165, 141, 224, 164, 176, 224, 164, 171, 224,
    164, 178, ' ', 224, 164, 149, 224, 165, 135, ' ', 224, 164,
    134, 224, 164, 167, 224, 164, 190, 224, 164, 176, ' ', 224,
    164, 170, 224, 164, 176, ' ', 224, 164, 181, 224, 164, 191,
    224, 164, 182, 224, 165, 141, 224, 164, 181, ' ', 224, 164,
    149, 224, 164, 190, ' ', 224, 164, 184, 224, 164, 190, 224,
    164, 164, 224, 164, 181, 224, 164, 190, 224, 164, 129, ' ',
    224, 164, 184, 224, 164, 172, 224, 164, 184, 224, 165, 135,
    ' ', 224, 164, 172, 224, 164, 161, 224, 164, 188, 224, 164,
    190, ' ', 224, 164, 176, 224, 164, 190, 224, 164, 183, 224,
    165, 141, 224, 164, 159, 224, 165, 141, 224, 164, 176, ' ',
    224, 164, 185, 224, 165, 136, 224, 165, 164, ' ', 224, 164,
    173, 224, 164, 190, 224, 164, 176, 224, 164, 164, ' ', 224,
    164, 149, 224, 165, 128, ' ', 224, 164, 176, 224, 164, 190,
    224, 164, 156, 224, 164, 167, 224, 164, 190, 224, 164, 168,
    224, 165, 128, ' ', 224, 164, 168, 224, 164, 136, ' ', 224,
    164, 166, 224, 164, 191, 224, 164, 178, 224, 165, 141, 224,
    164, 178, 224, 165, 128, ' ', 224, 164, 185, 224, 165, 136,
    224, 165, 164, ' ', 224, 164, 173, 224, 164, 190, 224, 164,
    176, 224, 164, 164, ' ', 224, 164, 149, 224, 165, 135, ' ',
    224, 164, 133, 224, 164, 168, 224, 165, 141, 224, 164, 175,
    ' ', 224, 164, 172, 224, 164, 161, 224, 164, 188, 224, 165,
    135, ' ', 224, 164, 174, 224, 164, 185, 224, 164, 190, 224,
    164, 168, 224, 164, 151, 224, 164, 176, ' ', 224, 164, 174,
    224, 165, 129, 224, 164, 174, 224, 165, 141, 224, 164, 172,
    224, 164, 136, ' ', '(', 224, 164, 172, 224, 164, 174, 224,
    165, 141, 224, 164, 172, 224, 164, 136, ')', ',', ' ', 224,
    164, 149, 224, 165, 139, 224, 164, 178, 224, 164, 149, 224,
    164, 190, 224, 164, 164, 224, 164, 190, ' ', '(', 224, 164,
    149, 224, 164, 178, 224, 164, 149, 224, 164, 164, 224, 165,
    141, 224, 164, 164, 224, 164, 190, ')', ' ', 224, 164, 148,
    224, 164, 176, ' ', 224, 164, 154, 224, 165, 135, 224, 164,
    168, 224, 165, 141, 224, 164, 168, 224, 164, 136, ' ', '(',
    224, 164, 174, 224, 164, 166, 224, 165, 141, 224, 164, 176,
    224, 164, 190, 224, 164, 184, ')', ' ', 224, 164, 185, 224,
    165, 136, 224, 164, 130, 224, 165, 164, ' ', 224, 165, 167,
    224, 165, 175, 224, 165, 170, 224, 165, 173, ' ', 224, 164,
    174, 224, 165, 135, 224, 164, 130, ' ', 224, 164, 184, 224,
    165, 141, 224, 164, 181, 224, 164, 164, 224, 164, 130, 224,
    164, 164, 224, 165, 141, 224, 164, 176, 224, 164, 164, 224,
    164, 190, ' ', 224, 164, 170, 224, 165, 141, 224, 164, 176,
    224, 164, 190, 224, 164, 170, 224, 165, 141, 224, 164, 164,
    224, 164, 191, ' ', 224, 164, 184, 224, 165, 135, ' ', 224,
    164, 170, 224, 165, 130, 224, 164, 176, 224, 165, 141, 224,
    164, 181, ' ', 224, 164, 172, 224, 165, 141, 224, 164, 176,
    224, 164, 191, 224, 164, 159, 224, 164, 191, 224, 164, 182,
    ' ', 224, 164, 173, 224, 164, 190, 224, 164, 176, 224, 164,
    164, ' ', 224, 164, 149, 224, 165, 135, ' ', 224, 164, 176,
    224, 165, 130, 224, 164, 170, ' ', 224, 164, 174, 224, 165,
    135, 224, 164, 130, ' ', 224, 164, 172, 224, 165, 141, 224,
    164, 176, 224, 164, 191, 224, 164, 159, 224, 164, 191, 224,
    164, 182, ' ', 224, 164, 184, 224, 164, 190, 224, 164, 174,
    224, 165, 141, 224, 164, 176, 224, 164, 190, 224, 164, 156,
    224, 165, 141, 224, 164, 175, ' ', 224, 164, 149, 224, 165,
    135, ' ', 224, 164, 170, 224, 165, 141, 224, 164, 176, 224,
    164, 174, 224, 165, 129, 224, 164, 150, ' ', 224, 164, 133,
    224, 164, 130, 224, 164, 151, ' ', 224, 164, 173, 224, 164,
    190, 224, 164, 176, 224, 164, 164, ' ', 224, 164, 168, 224,
    165, 135, ' ', 224, 164, 181, 224, 164, 191, 224, 164, 151,
    224, 164, 164, ' ', 224, 165, 168, 224, 165, 166, ' ', 224,
    164, 181, 224, 164, 176, 224, 165, 141, 224, 164, 183, ' ',
    224, 164, 174, 224, 165, 135, 224, 164, 130, ' ', 224, 164,
    184, 224, 164, 190, 224, 164, 176, 224, 165, 141, 224, 164,
    165, 224, 164, 149, ' ', 224, 164, 170, 224, 165, 141, 224,
    164, 176, 224, 164, 151, 224, 164, 164, 224, 164, 191, ' ',
    224, 164, 149, 224, 165, 128, ' ', 224, 164, 185, 224, 165,
    136, ',', ' ', 224, 164, 181, 224, 164, 191, 224, 164, 182,
    224, 165, 135, 224, 164, 183, ' ', 224, 164, 176, 224, 165,
    130, 224, 164, 170, ' ', 224, 164, 184, 224, 165, 135, ' ',
    224, 164, 134, 224, 164, 176, 224, 165, 141, 224, 164, 165,
    224, 164, 191, 224, 164, 149, ' ', 224, 164, 148, 224, 164,
    176, ' ', 224, 164, 173, 224, 164, 190, 224, 164, 176, 224,
    164, 164, 224, 165, 128, 224, 164, 175, ' ', 224, 164, 184,
    224, 165, 135, 224, 164, 168, 224, 164, 190, ' ', 224, 164,
    143, 224, 164, 149, ' ', 224, 164, 149, 224, 165, 141, 224,
    164, 183, 224, 165, 135, 224, 164, 164, 224, 165, 141, 224,
    164, 176, 224, 165, 128, 224, 164, 175, ' ', 224, 164, 182,
    224, 164, 149, 224, 165, 141, 224, 164, 164, 224, 164, 191,
    ' ', 224, 164, 148, 224, 164, 176, ' ', 224, 164, 181, 224,
    164, 191, 224, 164, 182, 224, 165, 141, 224, 164, 181, 224,
    164, 181, 224, 165, 141, 224, 164, 175, 224, 164, 190, 224,
    164, 170, 224, 164, 149, ' ', 224, 164, 182, 224, 164, 149,
    224, 165, 141, 224, 164, 164, 224, 164, 191, ' ', 224, 164,
    185, 224, 165, 136, 224, 165, 164, ' ', 224, 164, 173, 224,
    164, 190, 224, 164, 176, 224, 164, 164, ' ', 224, 164, 181,
    224, 164, 191, 224, 164, 182, 224, 165, 141, 224, 164, 181,
    ' ', 224, 164, 149, 224, 165, 128, ' ', 224, 164, 166, 224,
    164, 184, 224, 164, 181, 224, 165, 128, 224, 164, 130, ' ',
    224, 164, 184, 224, 164, 172, 224, 164, 184, 224, 165, 135,
    ' ', 224, 164, 172, 224, 164, 161, 224, 164, 188, 224, 165,
    128, ' ', 224, 164, 133, 224, 164, 176, 224, 165, 141, 224,
    164, 165, 224, 164, 181, 224, 165, 141, 224, 164, 175, 224,
    164, 181, 224, 164, 184, 224, 165, 141, 224, 164, 165, 224,
    164, 190, ' ', 224, 164, 185, 224, 165, 136, 224, 165, 164,
    ' ', 224, 164, 185, 224, 164, 190, 224, 164, 178, ' ', 224,
    164, 149, 224, 165, 135, ' ', 224, 164, 181, 224, 164, 176,
    224, 165, 141, 224, 164, 183, 224, 165, 139, 224, 164, 130,
    ' ', 224, 164, 174, 224, 165, 135, 224, 164, 130, ' ', 224,
    164, 173, 224, 164, 190, 224, 164, 176, 224, 164, 164, ' ',
    224, 164, 149, 224, 165, 128, ' ', 224, 164, 133, 224, 164,
    176, 224, 165, 141, 224, 164, 165, 224, 164, 181, 224, 165,
    141, 224, 164, 175, 224, 164, 181, 224, 164, 184, 224, 165,
    141, 224, 164, 165, 224, 164, 190, ' ', 224, 164, 168, 224,
    165, 135, ' ', 224, 164, 172, 224, 164, 185, 224, 165, 129,
    224, 164, 164, ' ', 224, 164, 170, 224, 165, 141, 224, 164,
    176, 224, 164, 151, 224, 164, 164, 224, 164, 191, ' ', 224,
    164, 149, 224, 165, 128, ' ', 224, 164, 185, 224, 165, 136,
    ',', ' ', 224, 164, 148, 224, 164, 176, ' ', 224, 164, 164,
    224, 164, 190, 224, 164, 156, 224, 164, 188, 224, 164, 190,
    ' ', 224, 164, 184, 224, 165, 141, 224, 164, 165, 224, 164,
    191, 224, 164, 164, 224, 164, 191, ' ', 224, 164, 174, 224,
    165, 135, 224, 164, 130, ' ', 224, 164, 173, 224, 164, 190,
    224, 164, 176, 224, 164, 164, ' ', 224, 164, 181, 224, 164,
    191, 224, 164, 182, 224, 165, 141, 224, 164, 181, ' ', 224,
    164, 174, 224, 165, 135, 224, 164, 130, ' ', 224, 164, 164,
    224, 165, 128, 224, 164, 184, 224, 164, 176, 224, 165, 135,
    '-', 224, 164, 154, 224, 165, 140, 224, 164, 165, 224, 165,
    135, ' ', 224, 164, 184, 224, 165, 141, 224, 164, 165, 224,
    164, 190, 224, 164, 168, ' ', 224, 164, 170, 224, 164, 176,
    ' ', 224, 164, 185, 224, 165, 139, 224, 164, 168, 224, 165,
    135, ' ', 224, 164, 149, 224, 164, 190, ' ', 224, 164, 166,
    224, 164, 190, 224, 164, 181, 224, 164, 190, ' ', 224, 164,
    149, 224, 164, 176, 224, 164, 164, 224, 164, 190, ' ', 224,
    164, 185, 224, 165, 136, ' ', 224, 165, 164,  13,  10,  13,
     10, 224, 164, 173, 224, 164, 190, 224, 164, 176, 224, 164,
    164, ' ', 224, 164, 149, 224, 165, 135, ' ', 224, 164, 166,
    224, 165, 139, ' ', 224, 164, 134, 224, 164, 167, 224, 164,
    191, 224, 164, 149, 224, 164, 190, 224, 164, 176, 224, 164,
    191, 224, 164, 149, ' ', 224, 164, 168, 224, 164, 190, 224,
    164, 174, ' ', 224, 164, 185, 224, 165, 136, 224, 164, 130,
    '-', ' ', 224, 164, 185, 224, 164, 191, 224, 164, 168, 224,
    165, 141, 224, 164, 166, 224, 165, 128, ' ', 224, 164, 174,
    224, 165, 135, 224, 164, 130, ' ', 224, 164, 173, 224, 164,
    190, 224, 164, 176, 224, 164, 164, ' ', 224, 164, 148, 224,
    164, 176, ' ', 224, 164, 133, 224, 164, 130, 224, 164, 151,
    224, 165, 141, 224, 164, 176, 224, 165, 135, 224, 164, 156,
    224, 164, 188, 224, 165, 128, ' ', 224, 164, 174, 224, 165,
    135, 224, 164, 130, ' ', 224, 164, 135, 224, 164, 163, 224,
    165, 141, 224, 164, 161, 224, 164, 191, 224, 164, 175, 224,
    164, 190, ' ', '(', 'I', 'n', 'd', 'i', 'a', ')', 224, 165,
    164, ' ', 224, 164, 135, 224, 164, 163, 224, 165, 141, 224,
    164, 161, 224, 164, 191, 224, 164, 175, 224, 164, 190, ' ',
    224, 164, 168, 224, 164, 190, 224, 164, 174, ' ', 224, 164,
    149, 224, 165, 128, ' ', 224, 164, 137, 224, 164, 164, 224,
    165, 141, 224, 164, 170, 224, 164, 164, 224, 165, 141, 224,
    164, 164, 224, 164, 191, ' ', 224, 164, 184, 224, 164, 191,
    224, 164, 168, 224, 165, 141, 224, 164, 167, 224, 165, 129,
    ' ', 224, 164, 168, 224, 164, 166, 224, 165, 128, ' ', 224,
    164, 149, 224, 165, 135, ' ', 224, 164, 133, 224, 164, 130,
    224, 164, 151, 224, 165, 141, 224, 164, 176, 224, 165, 135,
    224, 164, 156, 224, 165, 128, ' ', 224, 164, 168, 224, 164,
    190, 224, 164, 174, ' ', '"', 224, 164, 135, 224, 164, 163,
    224, 165, 141, 224, 164, 161, 224, 164, 184, '"', ' ', 224,
    164, 184, 224, 165, 135, ' ', 224, 164, 185, 224, 165, 129,
    224, 164, 136, ' ', 224, 164, 185, 224, 165, 136, 224, 165,
    164, ' ', 224, 164, 173, 224, 164, 190, 224, 164, 176, 224,
    164, 164, ' ', 224, 164, 168, 224, 164, 190, 224, 164, 174,
    ',', ' ', 224, 164, 143, 224, 164, 149, ' ', 224, 164, 170,
    224, 165, 141, 224, 164, 176, 224, 164, 190, 224, 164, 154,
    224, 165, 128, 224, 164, 168, ' ', 224, 164, 185, 224, 164,
    191, 224, 164, 168, 224, 165, 141, 224, 164, 166, 224, 165,
    130, ' ', 224, 164, 184, 224, 164, 174, 224, 165, 141, 224,
    164, 176, 224, 164, 190, 224, 164, 159, ' ', 224, 164, 173,
    224, 164, 176, 224, 164, 164, ' ', 224, 164, 156, 224, 165,
    139, ' ', 224, 164, 149, 224, 164, 191, ' ', 224, 164, 174,
    224, 164, 168, 224, 165, 129, ' ', 224, 164, 149, 224, 165,
    135, ' ', 224, 164, 181, 224, 164, 130, 224, 164, 182, 224,
    164, 156, ' ', 224, 164, 139, 224, 164, 183, 224, 164, 173,
    224, 164, 166, 224, 165, 135, 224, 164, 181, ' ', 224, 164,
    149, 224, 165, 135, ' ', 224, 164, 156, 224, 165, 141, 224,
    164, 175, 224, 165, 135, 224, 164, 183, 224, 165, 141, 224,
    164, 160, ' ', 224, 164, 170, 224, 165, 129, 224, 164, 164,
    224, 165, 141, 224, 164, 176, ' ', 224, 164, 165, 224, 165,
    135, ' ', 224, 164, 164, 224, 164, 165, 224, 164, 190, ' ',
    224, 164, 156, 224, 164, 191, 224, 164, 168, 224, 164, 149,
    224, 165, 128, ' ', 224, 164, 149, 224, 164, 165, 224, 164,
    190, ' ', 224, 164, 182, 224, 165, 141, 224, 164, 176, 224,
    165, 128, 224, 164, 174, 224, 164, 166, 224, 165, 141, 224,
    164, 173, 224, 164, 190, 224, 164, 151, 224, 164, 181, 224,
    164, 164, ' ', 224, 164, 174, 224, 164, 185, 224, 164, 190,
    224, 164, 170, 224, 165, 129, 224, 164, 176, 224, 164, 190,
    224, 164, 163, ' ', 224, 164, 174, 224, 165, 135, 224, 164,
    130, ' ', 224, 164, 185, 224, 165, 136, ',', ' ', 224, 164,
    149, 224, 165, 135, ' ', 224, 164, 168, 224, 164, 190, 224,
    164, 174, ' ', 224, 164, 184, 224, 165, 135, ' ', 224, 164,
    178, 224, 164, 191, 224, 164, 175, 224, 164, 190, ' ', 224,
    164, 151, 224, 164, 175, 224, 164, 190, ' ', 224, 164, 185,
    224, 165, 136, 224, 165, 164, ' ', 224, 164, 173, 224, 164,
    190, 224, 164, 176, 224, 164, 164, ' ', '(', 224, 164, 173,
    224, 164, 190, ' ', '+', ' ', 224, 164, 176, 224, 164, 164,
    ')', ' ', 224, 164, 182, 224, 164, 172, 224, 165, 141, 224,
    164, 166, ' ', 224, 164, 149, 224, 164, 190, ' ', 224, 164,
    174, 224, 164, 164, 224, 164, 178, 224, 164, 172, ' ', 224,
    164, 185, 224, 165, 136, ' ', 224, 164, 134, 224, 164, 168,
    224, 165, 141, 224, 164, 164, 224, 164, 176, 224, 164, 191,
    224, 164, 149, ' ', 224, 164, 170, 224, 165, 141, 224, 164,
    176, 224, 164, 149, 224, 164, 190, 224, 164, 182, ' ', 224,
    164, 175, 224, 164, 190, ' ', 224, 164, 181, 224, 164, 191,
    224, 164, 166, 224, 165, 135, 224, 164, 149, '-', 224, 164,
    176, 224, 165, 130, 224, 164, 170, 224, 165, 128, ' ', 224,
    164, 170, 224, 165, 141, 224, 164, 176, 224, 164, 149, 224,
    164, 190, 224, 164, 182, ' ', 224, 164, 174, 224, 165, 135,
    224, 164, 130, ' ', 224, 164, 178, 224, 165, 128, 224, 164,
    168, 224, 165, 164, ' ', 224, 164, 143, 224, 164, 149, ' ',
    224, 164, 164, 224, 165, 128, 224, 164, 184, 224, 164, 176,
    224, 164, 190, ' ', 224, 164, 168, 224, 164, 190, 224, 164,
    174, ' ', 224, 164, 185, 224, 164, 191, 224, 164, 168, 224,
    165, 141, 224, 164, 166, 224, 165, 129, 224, 164, 184, 224,
    165, 141, 224, 164, 164, 224, 164, 190, 224, 164, 168, ' ',
    224, 164, 173, 224, 165, 128, ' ', 224, 164, 185, 224, 165,
    136, ' ', 224, 164, 156, 224, 164, 191, 224, 164, 184, 224,
    164, 149, 224, 164, 190, ' ', 224, 164, 133, 224, 164, 176,
    224, 165, 141, 224, 164, 165, ' ', 224, 164, 185, 224, 164,
    191, 224, 164, 168, 224, 165, 141, 224, 164, 166, '(', 224,
    164, 185, 224, 164, 191, 224, 164, 168, 224, 165, 141, 224,
    164, 166, 224, 165, 130, ')', ' ', 224, 164, 149, 224, 165,
    128, ' ', 224, 164, 173, 224, 165, 130, 224, 164, 174, 224,
    164, 191, ' ', 224, 164, 185, 224, 165, 139, 224, 164, 164,
    224, 164, 190, ' ', 224, 164, 185, 224, 165, 136, ' ', 224,
    164, 156, 224, 165, 139, ' ', 224, 164, 149, 224, 164, 191,
    ' ', 224, 164, 170, 224, 165, 141, 224, 164, 176, 224, 164,
    190, 224, 164, 154, 224, 165, 128, 224, 164, 168, ' ', 224,
    164, 149, 224, 164, 190, 224, 164, 178, ' ', 224, 164, 139,
    224, 164, 183, 224, 164, 191, 224, 164, 175, 224, 165, 139,
    224, 164, 130, ' ', 224, 164, 166, 224, 165, 141, 224, 164,
    181, 224, 164, 190, 224, 164, 176, 224, 164, 190, ' ', 224,
    164, 166, 224, 164, 191, 224, 164, 175, 224, 164, 190, ' ',
    224, 164, 151, 224, 164, 175, 224, 164, 190, ' ', 224, 164,
    165, 224, 164, 190, 224, 165, 164, ' ', 224, 164, 170, 224,
    165, 141, 224, 164, 176, 224, 164, 190, 224, 164, 154, 224,
    165, 128, 224, 164, 168, ' ', 224, 164, 149, 224, 164, 190,
    224, 164, 178, ' ', 224, 164, 174, 224, 165, 135, 224, 164,
    130, ' ', 224, 164, 175, 224, 164, 185, ' ', 224, 164, 149,
    224, 164, 174, ' ', 224, 164, 170, 224, 165, 141, 224, 164,
    176, 224, 164, 175, 224, 165, 129, 224, 164, 149, 224, 165,
    141, 224, 164, 164, ' ', 224, 164, 185, 224, 165, 139, 224,
    164, 164, 224, 164, 190, ' ', 224, 164, 165, 224, 164, 190,
    ' ', 224, 164, 164, 224, 164, 165, 224, 164, 190, ' ', 224,
    164, 149, 224, 164, 190, 224, 164, 178, 224, 164, 190, 224,
    164, 168, 224, 165, 141, 224, 164, 164, 224, 164, 176, ' ',
    224, 164, 174, 224, 165, 135, 224, 164, 130, ' ', 224, 164,
    133, 224, 164, 167, 224, 164, 191, 224, 164, 149, ' ', 224,
    164, 170, 224, 165, 141, 224, 164, 176, 224, 164, 154, 224,
    164, 178, 224, 164, 191, 224, 164, 164, ' ', 224, 164, 185,
    224, 165, 129, 224, 164, 134, ' ', 224, 164, 181, 224, 164,
    191, 224, 164, 182, 224, 165, 135, 224, 164, 183, 224, 164,
    149, 224, 164, 176, ' ', 224, 164, 133, 224, 164, 176, 224,
    164, 172, '/', 224, 164, 136, 224, 164, 176, 224, 164, 190,
    224, 164, 168, ' ', 224, 164, 174, 224, 165, 135, 224, 164,
    130, 224, 165, 164, ' ', 224, 164, 173, 224, 164, 190, 224,
    164, 176, 224, 164, 164, ' ', 224, 164, 174, 224, 165, 135,
    224, 164, 130, ' ', 224, 164, 175, 224, 164, 185, ' ', 224,
    164, 168, 224, 164, 190, 224, 164, 174, ' ', 224, 164, 174,
    224, 165, 129, 224, 164, 151, 224, 164, 178, ' ', 224, 164,
    149, 224, 164, 190, 224, 164, 178, ' ', 224, 164, 184, 224,
    165, 135, ' ', 224, 164, 133, 224, 164, 167, 224, 164, 191,
    224, 164, 149, ' ', 224, 164, 170, 224, 165, 141, 224, 164,
    176, 224, 164, 154, 224, 164, 178, 224, 164, 191, 224, 164,
    164, ' ', 224, 164, 185, 224, 165, 129, 224, 164, 134, ' ',
    224, 164, 175, 224, 164, 166, 224, 165, 141, 224, 164, 175,
    224, 164, 170, 224, 164, 191, ' ', 224, 164, 135, 224, 164,
    184, 224, 164, 149, 224, 164, 190, ' ', 224, 164, 184, 224,
    164, 174, 224, 164, 149, 224, 164, 190, 224, 164, 178, 224,
    165, 128, 224, 164, 168, ' ', 224, 164, 137, 224, 164, 170,
    224, 164, 175, 224, 165, 139, 224, 164, 151, ' ', 224, 164,
    149, 224, 164, 174, ' ', 224, 164, 148, 224, 164, 176, ' ',
    224, 164, 170, 224, 165, 141, 224, 164, 176, 224, 164, 190,
    224, 164, 175, 224, 164, 131, ' ', 224, 164, 137, 224, 164,
    164, 224, 165, 141, 224, 164, 164, 224, 164, 176, 224, 165,
    128, ' ', 224, 164, 173, 224, 164, 190, 224, 164, 176, 224,
    164, 164, ' ', 224, 164, 149, 224, 165, 135, ' ', 224, 164,
    178, 224, 164, 191, 224, 164, 143, ' ', 224, 164, 185, 224,
    165, 139, 224, 164, 164, 224, 164, 190, ' ', 224, 164, 185,
    224, 165, 136, 224, 165, 164, ' ', 224, 164, 135, 224, 164,
    184, 224, 164, 149, 224, 165, 135, ' ', 224, 164, 133, 224,
    164, 164, 224, 164, 191, 224, 164, 176, 224, 164, 191, 224,
    164, 149, 224, 165, 141, 224, 164, 164, ' ', 224, 164, 173,
    224, 164, 190, 224, 164, 176, 224, 164, 164, 224, 164, 181,
    224, 164, 176, 224, 165, 141, 224, 164, 183, ' ', 224, 164,
    149, 224, 165, 139, ' ', 224, 164, 181, 224, 165, 136, 224,
    164, 166, 224, 164, 191, 224, 164, 149, ' ', 224, 164, 149,
    224, 164, 190, 224, 164, 178, ' ', 224, 164, 184, 224, 165,
    135, ' ', 224, 164, 134, 224, 164, 176, 224, 165, 141, 224,
    164, 175, 224, 164, 190, 224, 164, 181, 224, 164, 176, 224,
    165, 141, 224, 164, 164, ' ', '"', 224, 164, 156, 224, 164,
    174, 224, 165, 141, 224, 164, 172, 224, 165, 130, 224, 164,
    166, 224, 165, 141, 224, 164, 181, 224, 165, 128, 224, 164,
    170, '"', ' ', 224, 164, 148, 224, 164, 176, ' ', '"', 224,
    164, 133, 224, 164, 156, 224, 164, 168, 224, 164, 190, 224,
    164, 173, 224, 164, 166, 224, 165, 135, 224, 164, 182, '"',
    ' ', 224, 164, 149, 224, 165, 135, ' ', 224, 164, 168, 224,
    164, 190, 224, 164, 174, ' ', 224, 164, 184, 224, 165, 135,
    ' ', 224, 164, 173, 224, 165, 128, ' ', 224, 164, 156, 224,
    164, 190, 224, 164, 168, 224, 164, 190, ' ', 224, 164, 156,
    224, 164, 190, 224, 164, 164, 224, 164, 190, ' ', 224, 164,
    176, 224, 164, 185, 224, 164, 190, ' ', 224, 164, 185, 224,
    165, 136, 224, 165, 164, ' ', 224, 164, 172, 224, 164, 185,
    224, 165, 129, 224, 164, 164, ' ', 224, 164, 170, 224, 164,
    185, 224, 164, 178, 224, 165, 135, ' ', 224, 164, 175, 224,
    164, 185, ' ', 224, 164, 166, 224, 165, 135, 224, 164, 182,
    ' ','\'', 224, 164, 184, 224, 165, 139, 224, 164, 168, 224,
    165, 135, ' ', 224, 164, 149, 224, 165, 128, ' ', 224, 164,
    154, 224, 164, 191, 224, 164, 161, 224, 164, 188, 224, 164,
    191, 224, 164, 175, 224, 164, 190,'\'', ' ', 224, 164, 149,
    224, 165, 135, ' ', 224, 164, 176, 224, 165, 130, 224, 164,
    170, ' ', 224, 164, 174, 224, 165, 135, 224, 164, 130, ' ',
    224, 164, 156, 224, 164, 190, 224, 164, 168, 224, 164, 190,
    ' ', 224, 164, 156, 224, 164, 190, 224, 164, 164, 224, 164,
    190, ' ', 224, 164, 165, 224, 164, 190, 224, 165, 164, '[',
    '2', ']',  13,  10,  13,  10, 'F', 'r', 'e', 'n', 'c', 'h',
    ':',  13,  10,  13,  10, 'L', 'a', ' ', 'F', 'r', 'a', 'n',
    'c', 'e', ',', ' ', 'e', 'n', ' ', 'f', 'o', 'r', 'm', 'e',
    ' ', 'l', 'o', 'n', 'g', 'u', 'e', ' ', 'l', 'a', ' ', 'R',
    195, 169, 'p', 'u', 'b', 'l', 'i', 'q', 'u', 'e', ' ', 'f',
    'r', 'a', 'n', 195, 167, 'a', 'i', 's', 'e', ',', ' ', 'e',
    's', 't', ' ', 'u', 'n', 'e', ' ', 'r', 195, 169, 'p', 'u',
    'b', 'l', 'i', 'q', 'u', 'e', ' ', 'c', 'o', 'n', 's', 't',
    'i', 't', 'u', 't', 'i', 'o', 'n', 'n', 'e', 'l', 'l', 'e',
    ' ', 'u', 'n', 'i', 't', 'a', 'i', 'r', 'e', ' ', 'd', 'o',
    'n', 't', ' ', 'l', 'a', ' ', 'm', 'a', 'j', 'e', 'u', 'r',
    'e', ' ', 'p', 'a', 'r', 't', 'i', 'e', ' ', 'd', 'u', ' ',
    't', 'e', 'r', 'r', 'i', 't', 'o', 'i', 'r', 'e', ' ', 'e',
    't', ' ', 'd', 'e', ' ', 'l', 'a', ' ', 'p', 'o', 'p', 'u',
    'l', 'a', 't', 'i', 'o', 'n', ' ', 's', 'o', 'n', 't', ' ',
    's', 'i', 't', 'u', 195, 169, 's', ' ', 'e', 'n', ' ', 'E',
    'u', 'r', 'o', 'p', 'e', ' ', 'o', 'c', 'c', 'i', 'd', 'e',
    'n', 't', 'a', 'l', 'e', ',', ' ', 'm', 'a', 'i', 's', ' ',
    'q', 'u', 'i', ' ', 'c', 'o', 'm', 'p', 'r', 'e', 'n', 'd',
    ' ', 195, 169, 'g', 'a', 'l', 'e', 'm', 'e', 'n', 't', ' ',
    'p', 'l', 'u', 's', 'i', 'e', 'u', 'r', 's', ' ', 'r', 195,
    169, 'g', 'i', 'o', 'n', 's', ' ', 'e', 't', ' ', 't', 'e',
    'r', 'r', 'i', 't', 'o', 'i', 'r', 'e', 's', ' ', 'r', 195,
    169, 'p', 'a', 'r', 't', 'i', 's', ' ', 'd', 'a', 'n', 's',
    ' ', 'l', 'e', 's', ' ', 'A', 'm', 195, 169, 'r', 'i', 'q',
    'u', 'e', 's', ',', ' ', 'l', 226, 128, 153, 'o', 'c', 195,
    169, 'a', 'n', ' ', 'I', 'n', 'd', 'i', 'e', 'n', ' ', 'e',
    't', ' ', 'l','\'', 'o', 'c', 195, 169, 'a', 'n', ' ', 'P',
    'a', 'c', 'i', 'f', 'i', 'q', 'u', 'e', '.', ' ', 'E', 'l',
    'l', 'e', ' ', 'a', ' ', 'p', 'o', 'u', 'r', ' ', 'c', 'a',
    'p', 'i', 't', 'a', 'l', 'e', ' ', 'P', 'a', 'r', 'i', 's',
    ',', ' ', 'p', 'o', 'u', 'r', ' ', 'l', 'a', 'n', 'g', 'u',
    'e', ' ', 'o', 'f', 'f', 'i', 'c', 'i', 'e', 'l', 'l', 'e',
    ' ', 'l', 'e', ' ', 'f', 'r', 'a', 'n', 195, 167, 'a', 'i',
    's', ' ', 'e', 't', ' ', 'p', 'o', 'u', 'r', ' ', 'm', 'o',
    'n', 'n', 'a', 'i', 'e', ' ', 'l', 226, 128, 153, 'e', 'u',
    'r', 'o', '.', ' ', 'S', 'a', ' ', 'd', 'e', 'v', 'i', 's',
    'e', ' ', 'e', 's', 't', ' ', 194, 171, ' ', 'L', 'i', 'b',
    'e', 'r', 't', 195, 169, ',', ' ', 195, 137, 'g', 'a', 'l',
    'i', 't', 195, 169, ',', ' ', 'F', 'r', 'a', 't', 'e', 'r',
    'n', 'i', 't', 195, 169, ' ', 194, 187, ',', ' ', 'e', 't',
    ' ', 's', 'o', 'n', ' ', 'd', 'r', 'a', 'p', 'e', 'a', 'u',
    ' ', 'e', 's', 't', ' ', 'c', 'o', 'n', 's', 't', 'i', 't',
    'u', 195, 169, ' ', 'd', 'e', ' ', 't', 'r', 'o', 'i', 's',
    ' ', 'b', 'a', 'n', 'd', 'e', 's', ' ', 'v', 'e', 'r', 't',
    'i', 'c', 'a', 'l', 'e', 's', ' ', 'r', 'e', 's', 'p', 'e',
    'c', 't', 'i', 'v', 'e', 'm', 'e', 'n', 't', ' ', 'b', 'l',
    'e', 'u', 'e', ',', ' ', 'b', 'l', 'a', 'n', 'c', 'h', 'e',
    ' ', 'e', 't', ' ', 'r', 'o', 'u', 'g', 'e', '.', ' ', 'S',
    'o', 'n', ' ', 'h', 'y', 'm', 'n', 'e', ' ', 'e', 's', 't',
    ' ', 'L', 'a', ' ', 'M', 'a', 'r', 's', 'e', 'i', 'l', 'l',
    'a', 'i', 's', 'e', '.', ' ', 'S', 'o', 'n', ' ', 'p', 'r',
    'i', 'n', 'c', 'i', 'p', 'e', ' ', 'e', 's', 't', ' ', 'g',
    'o', 'u', 'v', 'e', 'r', 'n', 'e', 'm', 'e', 'n', 't', ' ',
    'd', 'u', ' ', 'p', 'e', 'u', 'p', 'l', 'e', ',', ' ', 'p',
    'a', 'r', ' ', 'l', 'e', ' ', 'p', 'e', 'u', 'p', 'l', 'e',
    ' ', 'e', 't', ' ', 'p', 'o', 'u', 'r', ' ', 'l', 'e', ' ',
    'p', 'e', 'u', 'p', 'l', 'e', '[', '3', ']', '.',  13,  10,
     13,  10, 'L', 'a', ' ', 'F', 'r', 'a', 'n', 'c', 'e', ' ',
    'e', 's', 't', ' ', 'u', 'n', ' ', 'p', 'a', 'y', 's', ' ',
    'a', 'n', 'c', 'i', 'e', 'n', ',', ' ', 'f', 'o', 'r', 'm',
    195, 169, ' ', 'a', 'u', ' ', 'H', 'a', 'u', 't', ' ', 'M',
    'o', 'y', 'e', 'n', ' ', 195, 130, 'g', 'e', '.', ' ', 'A',
    'u', ' ', 'X', 'I', 'X', 'e', ' ', 's', 'i', 195, 168, 'c',
    'l', 'e', ' ', 'e', 't', ' ', 'd', 'a', 'n', 's', ' ', 'l',
    'a', ' ', 'p', 'r', 'e', 'm', 'i', 195, 168, 'r', 'e', ' ',
    'm', 'o', 'i', 't', 'i', 195, 169, ' ', 'd', 'u', ' ', 'X',
    'X', 'e', ' ', 's', 'i', 195, 168, 'c', 'l', 'e', ',', ' ',
    'e', 'l', 'l', 'e', ' ', 'p', 'o', 's', 's', 195, 168, 'd',
    'e', ' ', 'u', 'n', ' ', 'v', 'a', 's', 't', 'e', ' ', 'e',
    'm', 'p', 'i', 'r', 'e', ' ', 'c', 'o', 'l', 'o', 'n', 'i',
    'a', 'l', '.', ' ', 195, 128, ' ', 'p', 'a', 'r', 't', 'i',
    'r', ' ', 'd', 'e', 's', ' ', 'a', 'n', 'n', 195, 169, 'e',
    's', ' ', '1', '9', '5', '0', ',', ' ', 'e', 'l', 'l', 'e',
    ' ', 'e', 's', 't', ' ', 'l', 226, 128, 153, 'u', 'n', ' ',
    'd', 'e', 's', ' ', 'a', 'c', 't', 'e', 'u', 'r', 's', ' ',
    'd', 'e', ' ', 'l', 'a', ' ', 'c', 'o', 'n', 's', 't', 'r',
    'u', 'c', 't', 'i', 'o', 'n', ' ', 'd', 'e', ' ', 'l', 226,
    128, 153, 'U', 'n', 'i', 'o', 'n', ' ', 'e', 'u', 'r', 'o',
    'p', 195, 169, 'e', 'n', 'n', 'e', '.', ' ', 'E', 'l', 'l',
    'e', ' ', 'e', 's', 't', ' ', 'u', 'n', 'e', ' ', 'p', 'u',
    'i', 's', 's', 'a', 'n', 'c', 'e', ' ', 'n', 'u', 'c', 'l',
    195, 169, 'a', 'i', 'r', 'e', ',', ' ', 'e', 't', ' ', 'l',
    226, 128, 153, 'u', 'n', ' ', 'd', 'e', 's', ' ', 'c', 'i',
    'n', 'q', ' ', 'm', 'e', 'm', 'b', 'r', 'e', 's', ' ', 'p',
    'e', 'r', 'm', 'a', 'n', 'e', 'n', 't', 's', ' ', 'd', 'u',
    ' ', 'C', 'o', 'n', 's', 'e', 'i', 'l', ' ', 'd', 'e', ' ',
    's', 195, 169, 'c', 'u', 'r', 'i', 't', 195, 169, ' ', 'd',
    'e', 's', ' ', 'N', 'a', 't', 'i', 'o', 'n', 's', ' ', 'u',
    'n', 'i', 'e', 's', '.', ' ', 'L', 'a', ' ', 'F', 'r', 'a',
    'n', 'c', 'e', ' ', 'j', 'o', 'u', 'e', ' ', 'u', 'n', ' ',
    'r', 195, 180, 'l', 'e', ' ', 'i', 'm', 'p', 'o', 'r', 't',
    'a', 'n', 't', ' ', 'd', 'a', 'n', 's', ' ', 'l', 226, 128,
    153, 'h', 'i', 's', 't', 'o', 'i', 'r', 'e', ' ', 'm', 'o',
    'n', 'd', 'i', 'a', 'l', 'e', ' ', 'p', 'a', 'r', ' ', 'l',
    226, 128, 153, 'i', 'n', 'f', 'l', 'u', 'e', 'n', 'c', 'e',
    ' ', 'd', 'e', ' ', 's', 'a', ' ', 'c', 'u', 'l', 't', 'u',
    'r', 'e', ' ', 'e', 't', ' ', 'd', 'e', ' ', 's', 'e', 's',
    ' ', 'v', 'a', 'l', 'e', 'u', 'r', 's', ' ', 'd', 195, 169,
    'm', 'o', 'c', 'r', 'a', 't', 'i', 'q', 'u', 'e', 's', ',',
    ' ', 'l', 'a', 195, 175, 'q', 'u', 'e', 's', ' ', 'e', 't',
    ' ', 'r', 195, 169, 'p', 'u', 'b', 'l', 'i', 'c', 'a', 'i',
    'n', 'e', 's', '.',  13,  10,  13,  10, 'L', 'a', ' ', 'F',
    'r', 'a', 'n', 'c', 'e', ' ', 'a', ',', ' ', 'e', 'n', ' ',
    '2', '0', '1', '0', ',', ' ', 'l', 'e', ' ', 'c', 'i', 'n',
    'q', 'u', 'i', 195, 168, 'm', 'e', ' ', 'p', 'l', 'u', 's',
    ' ', 'i', 'm', 'p', 'o', 'r', 't', 'a', 'n', 't', ' ', 'p',
    'r', 'o', 'd', 'u', 'i', 't', ' ', 'i', 'n', 't', 195, 169,
    'r', 'i', 'e', 'u', 'r', ' ', 'b', 'r', 'u', 't', ' ', 'a',
    'u', ' ', 'm', 'o', 'n', 'd', 'e', '.', ' ', 'S', 'o', 'n',
    ' ', 195, 169, 'c', 'o', 'n', 'o', 'm', 'i', 'e', ',', ' ',
    'd', 'e', ' ', 't', 'y', 'p', 'e', ' ', 'c', 'a', 'p', 'i',
    't', 'a', 'l', 'i', 's', 't', 'e', ' ', 'a', 'v', 'e', 'c',
    ' ', 'u', 'n', 'e', ' ', 'i', 'n', 't', 'e', 'r', 'v', 'e',
    'n', 't', 'i', 'o', 'n', ' ', 195, 169, 't', 'a', 't', 'i',
    'q', 'u', 'e', ' ', 'a', 's', 's', 'e', 'z', ' ', 'f', 'o',
    'r', 't', 'e', ',', ' ', 'f', 'a', 'i', 't', ' ', 'd', 226,
    128, 153, 'e', 'l', 'l', 'e', ' ', 'u', 'n', ' ', 'd', 'e',
    's', ' ', 'l', 'e', 'a', 'd', 'e', 'r', 's', ' ', 'm', 'o',
    'n', 'd', 'i', 'a', 'u', 'x', ' ', 'd', 'a', 'n', 's', ' ',
    'l', 'e', 's', ' ', 's', 'e', 'c', 't', 'e', 'u', 'r', 's',
    ' ', 'd', 'e', ' ', 'l', 226, 128, 153, 'a', 'g', 'r', 'o',
    'a', 'l', 'i', 'm', 'e', 'n', 't', 'a', 'i', 'r', 'e', ',',
    ' ', 'd', 'e', ' ', 'l', 226, 128, 153, 'a', 195, 169, 'r',
    'o', 'n', 'a', 'u', 't', 'i', 'q', 'u', 'e', ',', ' ', 'd',
    'e', ' ', 'l', 226, 128, 153, 'a', 'u', 't', 'o', 'm', 'o',
    'b', 'i', 'l', 'e', ',', ' ', 'd', 'e', 's', ' ', 'p', 'r',
    'o', 'd', 'u', 'i', 't', 's', ' ', 'd', 'e', ' ', 'l', 'u',
    'x', 'e', ',', ' ', 'd', 'u', ' ', 't', 'o', 'u', 'r', 'i',
    's', 'm', 'e', ' ', 'e', 't', ' ', 'd', 'u', ' ', 'n', 'u',
    'c', 'l', 195, 169, 'a', 'i', 'r', 'e', '.',  13,  10,  13,
     10, 'P', 'e', 'u', 'p', 'l', 195, 169, 'e', ' ', 'd', 'e',
    ' ', '6', '5', ',', '3', ' ', 'm', 'i', 'l', 'l', 'i', 'o',
    'n', 's', ' ', 'd', 226, 128, 153, 'h', 'a', 'b', 'i', 't',
    'a', 'n', 't', 's', ' ', 'a', 'u', ' ', '1', 'e', 'r', ' ',
    'j', 'a', 'n', 'v', 'i', 'e', 'r', ' ', '2', '0', '1', '2',
    '[', '4', ']', ',', ' ', 'l', 'a', ' ', 'F', 'r', 'a', 'n',
    'c', 'e', ' ', 'e', 's', 't', ' ', 'u', 'n', ' ', 'p', 'a',
    'y', 's', ' ', 'd', 195, 169, 'v', 'e', 'l', 'o', 'p', 'p',
    195, 169, ',', ' ', 'a', 'v', 'e', 'c', ' ', 'u', 'n', ' ',
    'i', 'n', 'd', 'i', 'c', 'e', ' ', 'd', 'e', ' ', 'd', 195,
    169, 'v', 'e', 'l', 'o', 'p', 'p', 'e', 'm', 'e', 'n', 't',
    ' ', 'h', 'u', 'm', 'a', 'i', 'n', ' ', 't', 'r', 195, 168,
    's', ' ', 195, 169, 'l', 'e', 'v', 195, 169, '[', '5', ']',
    '.',  13,  10,  13,  10, 'L', 'a', ' ', 'F', 'r', 'a', 'n',
    'c', 'e', ' ', 'm', 195, 169, 't', 'r', 'o', 'p', 'o', 'l',
    'i', 't', 'a', 'i', 'n', 'e', ' ', 'e', 's', 't', ' ', 's',
    'i', 't', 'u', 195, 169, 'e', ' ', 195, 160, ' ', 'l', 226,
    128, 153, 'u', 'n', 'e', ' ', 'd', 'e', 's', ' ', 'e', 'x',
    't', 'r', 195, 169, 'm', 'i', 't', 195, 169, 's', ' ', 'o',
    'c', 'c', 'i', 'd', 'e', 'n', 't', 'a', 'l', 'e', 's', ' ',
    'd', 'e', ' ', 'l', 226, 128, 153, 'E', 'u', 'r', 'o', 'p',
    'e', '.', ' ', 'E', 'l', 'l', 'e', ' ', 'e', 's', 't', ' ',
    'b', 'o', 'r', 'd', 195, 169, 'e', ' ', 'p', 'a', 'r', ' ',
    'l', 'a', ' ', 'm', 'e', 'r', ' ', 'd', 'u', ' ', 'N', 'o',
    'r', 'd', ' ', 'a', 'u', ' ', 'n', 'o', 'r', 'd', ',', ' ',
    'l', 'a', ' ', 'M', 'a', 'n', 'c', 'h', 'e', ' ', 'a', 'u',
    ' ', 'n', 'o', 'r', 'd', '-', 'o', 'u', 'e', 's', 't', ',',
    ' ', 'l', 226, 128, 153, 'o', 'c', 195, 169, 'a', 'n', ' ',
    'A', 't', 'l', 'a', 'n', 't', 'i', 'q', 'u', 'e', ' ', 195,
    160, ' ', 'l', 226, 128, 153, 'o', 'u', 'e', 's', 't', ' ',
    'e', 't', ' ', 'l', 'a', ' ', 'm', 'e', 'r', ' ', 'M', 195,
    169, 'd', 'i', 't', 'e', 'r', 'r', 'a', 'n', 195, 169, 'e',
    ' ', 'a', 'u', ' ', 's', 'u', 'd', '-', 'e', 's', 't', '.',
    ' ', 'E', 'l', 'l', 'e', ' ', 'e', 's', 't', ' ', 'f', 'r',
    'o', 'n', 't', 'a', 'l', 'i', 195, 168, 'r', 'e', ' ', 'd',
    'e', ' ', 'l', 'a', ' ', 'B', 'e', 'l', 'g', 'i', 'q', 'u',
    'e', ' ', 'e', 't', ' ', 'd', 'u', ' ', 'L', 'u', 'x', 'e',
    'm', 'b', 'o', 'u', 'r', 'g', ' ', 'a', 'u', ' ', 'n', 'o',
    'r', 'd', '-', 'e', 's', 't', ',', ' ', 'd', 'e', ' ', 'l',
    226, 128, 153, 'A', 'l', 'l', 'e', 'm', 'a', 'g', 'n', 'e',
    ' ', 'e', 't', ' ', 'd', 'e', ' ', 'l', 'a', ' ', 'S', 'u',
    'i', 's', 's', 'e', ' ', 195, 160, ' ', 'l', 226, 128, 153,
    'e', 's', 't', ',', ' ', 'd', 'e', ' ', 'l', 226, 128, 153,
    'I', 't', 'a', 'l', 'i', 'e', ' ', 'e', 't', ' ', 'd', 'e',
    ' ', 'M', 'o', 'n', 'a', 'c', 'o', ' ', 'a', 'u', ' ', 's',
    'u', 'd', '-', 'e', 's', 't', ',', ' ', 'd', 'e', ' ', 'l',
    226, 128, 153, 'E', 's', 'p', 'a', 'g', 'n', 'e', ' ', 'e',
    't', ' ', 'd', 226, 128, 153, 'A', 'n', 'd', 'o', 'r', 'r',
    'e', ' ', 'a', 'u', ' ', 's', 'u', 'd', '-', 'o', 'u', 'e',
    's', 't', '.', ' ', 'S', 'i', ' ', 'l', 'e', 's', ' ', 'f',
    'r', 'o', 'n', 't', 'i', 195, 168, 'r', 'e', 's', ' ', 'd',
    'u', ' ', 's', 'u', 'd', ' ', 'd', 'u', ' ', 'p', 'a', 'y',
    's', ' ', 'c', 'o', 'r', 'r', 'e', 's', 'p', 'o', 'n', 'd',
    'e', 'n', 't', ' ', 195, 160, ' ', 'd', 'e', 's', ' ', 'm',
    'a', 's', 's', 'i', 'f', 's', ' ', 'm', 'o', 'n', 't', 'a',
    'g', 'n', 'e', 'u', 'x', ',', ' ', 'l', 'e', 's', ' ', 'f',
    'r', 'o', 'n', 't', 'i', 195, 168, 'r', 'e', 's', ' ', 'd',
    'u', ' ', 'n', 'o', 'r', 'd', '-', 'e', 's', 't', ' ', 'n',
    'e', ' ', 'c', 'o', 'r', 'r', 'e', 's', 'p', 'o', 'n', 'd',
    'e', 'n', 't', ' ', 195, 160, ' ', 'a', 'u', 'c', 'u', 'n',
    'e', ' ', 'l', 'i', 'm', 'i', 't', 'e', ' ', 'g', 195, 169,
    'o', 'g', 'r', 'a', 'p', 'h', 'i', 'q', 'u', 'e', '[', 'n',
    'o', 't', 'e', ' ', '6', ']', ' ', 'n', 'i', ' ', 'l', 'i',
    'n', 'g', 'u', 'i', 's', 't', 'i', 'q', 'u', 'e', '[', 'n',
    'o', 't', 'e', ' ', '7', ']', '.', ' ', 'L', 'a', ' ', 'F',
    'r', 'a', 'n', 'c', 'e', ' ', 'm', 195, 169, 't', 'r', 'o',
    'p', 'o', 'l', 'i', 't', 'a', 'i', 'n', 'e', ' ', 'c', 'o',
    'm', 'p', 'r', 'e', 'n', 'd', ' ', 'p', 'l', 'u', 's', 'i',
    'e', 'u', 'r', 's', ' ', 195, 174, 'l', 'e', 's', ',', ' ',
    'n', 'o', 't', 'a', 'm', 'm', 'e', 'n', 't', ' ', 'l', 'a',
    ' ', 'C', 'o', 'r', 's', 'e', ' ', 'e', 't', ' ', 'd', 'e',
    's', ' ', 195, 174, 'l', 'e', 's', ' ', 'c', 195, 180, 't',
    'i', 195, 168, 'r', 'e', 's', '.', ' ', 'L', 'a', ' ', 'm',
    195, 169, 't', 'r', 'o', 'p', 'o', 'l', 'e', ' ', 'e', 's',
    't', ' ', 'c', 'o', 'm', 'p', 'r', 'i', 's', 'e', ' ', 'e',
    'n', 't', 'r', 'e', ' ', 'l', 'e', 's', ' ', 'l', 'a', 't',
    'i', 't', 'u', 'd', 'e', 's', ' ', '4', '2', 194, 176, '1',
    '9','\'', '4', '6', '"', ' ', 'N', ' ', 'e', 't', ' ', '5',
    '1', 194, 176, '5','\'', '4', '7', '"', ' ', 'N', ',', ' ',
    'a', 'i', 'n', 's', 'i', ' ', 'q', 'u', 'e', ' ', 'l', 'e',
    's', ' ', 'l', 'o', 'n', 'g', 'i', 't', 'u', 'd', 'e', 's',
    ' ', '4', 194, 176, '4', '6','\'', ' ', 'O', ' ', 'e', 't',
    ' ', '8', 194, 176, '1', '4','\'', '4', '2', '"', ' ', 'E',
    '.',  13,  10,  13,  10, 'L', 'a', ' ', 'F', 'r', 'a', 'n',
    'c', 'e', ' ', 'c', 'o', 'm', 'p', 'r', 'e', 'n', 'd', ' ',
    195, 169, 'g', 'a', 'l', 'e', 'm', 'e', 'n', 't', ' ', 'd',
    'e', ' ', 'n', 'o', 'm', 'b', 'r', 'e', 'u', 'x', ' ', 't',
    'e', 'r', 'r', 'i', 't', 'o', 'i', 'r', 'e', 's', ' ', 's',
    'i', 't', 'u', 195, 169, 's', ' ', 'e', 'n', '-', 'd', 'e',
    'h', 'o', 'r', 's', ' ', 'd', 'u', ' ', 'c', 'o', 'n', 't',
    'i', 'n', 'e', 'n', 't', ' ', 'e', 'u', 'r', 'o', 'p', 195,
    169, 'e', 'n', ',', ' ', 'c', 'o', 'u', 'r', 'a', 'm', 'm',
    'e', 'n', 't', ' ', 'a', 'p', 'p', 'e', 'l', 195, 169, 's',
    ' ', 't', 'e', 'r', 'r', 'i', 't', 'o', 'i', 'r', 'e', 's',
    ' ', 'd', 226, 128, 153, 'o', 'u', 't', 'r', 'e', '-', 'm',
    'e', 'r', ',', ' ', 'n', 'a', 'g', 'u', 195, 168, 'r', 'e',
    ' ', 'D', 'O', 'M', '-', 'T', 'O', 'M', ',', ' ', 'q', 'u',
    'i', ' ', 'l', 'u', 'i', ' ', 'p', 'e', 'r', 'm', 'e', 't',
    't', 'e', 'n', 't', ' ', 'd', 226, 128, 153, 195, 170, 't',
    'r', 'e', ' ', 'p', 'r', 195, 169, 's', 'e', 'n', 't', 'e',
    ' ', 'd', 'a', 'n', 's', ' ', 't', 'o', 'u', 's', ' ', 'l',
    'e', 's', ' ', 'o', 'c', 195, 169, 'a', 'n', 's', '.', ' ',
    'C', 'e', 's', ' ', 't', 'e', 'r', 'r', 'i', 't', 'o', 'i',
    'r', 'e', 's', ' ', 'a', 'u', 'x', ' ', 's', 't', 'a', 't',
    'u', 't', 's', ' ', 'v', 'a', 'r', 'i', 195, 169, 's', ' ',
    's', 'o', 'n', 't', '[', '6', ']', ' ', ':',  13,  10,  13,
     10, 's', 'u', 'r', ' ', 'l', 'e', ' ', 'c', 'o', 'n', 't',
    'i', 'n', 'e', 'n', 't', ' ', 's', 'u', 'd', '-', 'a', 'm',
    195, 169, 'r', 'i', 'c', 'a', 'i', 'n', ' ', ':', ' ', 'l',
    'a', ' ', 'G', 'u', 'y', 'a', 'n', 'e', ' ', ';',  13,  10,
    'd', 'a', 'n', 's', ' ', 'l', 226, 128, 153, 'o', 'c', 195,
    169, 'a', 'n', ' ', 'A', 't', 'l', 'a', 'n', 't', 'i', 'q',
    'u', 'e', ' ', '(', 'A', 'n', 't', 'i', 'l', 'l', 'e', 's',
    ')', ' ', ':', ' ', 'l', 'a', ' ', 'G', 'u', 'a', 'd', 'e',
    'l', 'o', 'u', 'p', 'e', ',', ' ', 'l', 'a', ' ', 'M', 'a',
    'r', 't', 'i', 'n', 'i', 'q', 'u', 'e', ',', ' ', 'S', 'a',
    'i', 'n', 't', '-', 'P', 'i', 'e', 'r', 'r', 'e', '-', 'e',
    't', '-', 'M', 'i', 'q', 'u', 'e', 'l', 'o', 'n', ',', ' ',
    'S', 'a', 'i', 'n', 't', '-', 'M', 'a', 'r', 't', 'i', 'n',
    ' ', 'e', 't', ' ', 'S', 'a', 'i', 'n', 't', '-', 'B', 'a',
    'r', 't', 'h', 195, 169, 'l', 'e', 'm', 'y', ' ', ';',  13,
     10, 'd', 'a', 'n', 's', ' ', 'l', 226, 128, 153, 'o', 'c',
    195, 169, 'a', 'n', ' ', 'P', 'a', 'c', 'i', 'f', 'i', 'q',
    'u', 'e', ' ', ':', ' ', 'l', 'a', ' ', 'P', 'o', 'l', 'y',
    'n', 195, 169, 's', 'i', 'e', ' ', 'f', 'r', 'a', 'n', 195,
    167, 'a', 'i', 's', 'e', ',', ' ', 'l', 'a', ' ', 'N', 'o',
    'u', 'v', 'e', 'l', 'l', 'e', '-', 'C', 'a', 'l', 195, 169,
    'd', 'o', 'n', 'i', 'e', ',', ' ', 'W', 'a', 'l', 'l', 'i',
    's', '-', 'e', 't', '-', 'F', 'u', 't', 'u', 'n', 'a', ' ',
    'e', 't', ' ', 'C', 'l', 'i', 'p', 'p', 'e', 'r', 't', 'o',
    'n', ' ', ';',  13,  10, 'd', 'a', 'n', 's', ' ', 'l', 226,
    128, 153, 'o', 'c', 195, 169, 'a', 'n', ' ', 'I', 'n', 'd',
    'i', 'e', 'n', ' ', ':', ' ', 'L', 'a', ' ', 'R', 195, 169,
    'u', 'n', 'i', 'o', 'n', ',', ' ', 'M', 'a', 'y', 'o', 't',
    't', 'e', ',', ' ', 'l', 'e', 's', ' ', 195, 142, 'l', 'e',
    's', ' ', 195, 137, 'p', 'a', 'r', 's', 'e', 's', ',', ' ',
    'l', 'e', 's', ' ', 195, 142, 'l', 'e', 's', ' ', 'C', 'r',
    'o', 'z', 'e', 't', ',', ' ', 'l', 'e', 's', ' ', 195, 142,
    'l', 'e', 's', ' ', 'K', 'e', 'r', 'g', 'u', 'e', 'l', 'e',
    'n', ' ', 'e', 't', ' ', 'S', 'a', 'i', 'n', 't', '-', 'P',
    'a', 'u', 'l', '-', 'e', 't', '-', 'A', 'm', 's', 't', 'e',
    'r', 'd', 'a', 'm', ' ', ';',  13,  10, 'e', 'n', ' ', 'A',
    'n', 't', 'a', 'r', 'c', 't', 'i', 'q', 'u', 'e', ' ', ':',
    ' ', 'l', 'a', ' ', 'T', 'e', 'r', 'r', 'e', ' ', 'A', 'd',
    195, 169, 'l', 'i', 'e', '[', 'n', 'o', 't', 'e', ' ', '8',
    ']', '.',  13,  10, 195, 128, ' ', 't', 'r', 'a', 'v', 'e',
    'r', 's', ' ', 's', 'e', 's', ' ', 'c', 'o', 'l', 'l', 'e',
    'c', 't', 'i', 'v', 'i', 't', 195, 169, 's', ' ', 'u', 'l',
    't', 'r', 'a', '-', 'm', 'a', 'r', 'i', 'n', 'e', 's', ',',
    ' ', 'l', 'a', ' ', 'F', 'r', 'a', 'n', 'c', 'e', ' ', 'p',
    'o', 's', 's', 195, 168, 'd', 'e', ' ', 195, 169, 'g', 'a',
    'l', 'e', 'm', 'e', 'n', 't', ' ', 'd', 'e', 's', ' ', 'f',
    'r', 'o', 'n', 't', 'i', 195, 168, 'r', 'e', 's', ' ', 't',
    'e', 'r', 'r', 'e', 's', 't', 'r', 'e', 's', ' ', 'a', 'v',
    'e', 'c', ' ', 'l', 'e', ' ', 'B', 'r', 195, 169, 's', 'i',
    'l', ' ', 'e', 't', ' ', 'l', 'e', ' ', 'S', 'u', 'r', 'i',
    'n', 'a', 'm', 'e', ',', ' ', 'a', 'i', 'n', 's', 'i', ' ',
    'q', 'u', 226, 128, 153, 'a', 'v', 'e', 'c', ' ', 'l', 'e',
    's', ' ', 'P', 'a', 'y', 's', '-', 'B', 'a', 's', ' ', 'v',
    'i', 'a', ' ', 'l', 'a', ' ', 'p', 'a', 'r', 't', 'i', 'e',
    ' ', 'f', 'r', 'a', 'n', 195, 167, 'a', 'i', 's', 'e', ' ',
    'd', 'e', ' ', 'S', 'a', 'i', 'n', 't', '-', 'M', 'a', 'r',
    't', 'i', 'n', '.',  13,  10,  13,  10, 'L', 'a', ' ', 's',
    'u', 'p', 'e', 'r', 'f', 'i', 'c', 'i', 'e', ' ', 'd', 'e',
    ' ', 'l', 'a', ' ', 'F', 'r', 'a', 'n', 'c', 'e', ' ', 'e',
    's', 't', ' ', 'd', 'e', ' ', '6', '7', '0', ' ', '9', '2',
    '2', ' ', 'k', 'm', 194, 178, ',', ' ', 'o', 'u', ' ', '5',
    '4', '7', ' ', '0', '3', '0', ' ', 's', 'a', 'n', 's', ' ',
    'c', 'o', 'm', 'p', 't', 'a', 'b', 'i', 'l', 'i', 's', 'e',
    'r', ' ', 'l', 226, 128, 153, 'o', 'u', 't', 'r', 'e', '-',
    'm', 'e', 'r', '[', '7', ']', '.', ' ', 'E', 'l', 'l', 'e',
    ' ', 'e', 's', 't', ' ', 'l', 'e', ' ', '4', '1', 'e', ' ',
    'p', 'l', 'u', 's', ' ', 'g', 'r', 'a', 'n', 'd', ' ', 195,
    137, 't', 'a', 't', ' ', 'd', 'u', ' ', 'm', 'o', 'n', 'd',
    'e', ' ', 'p', 'a', 'r', ' ', 's', 'a', ' ', 's', 'u', 'r',
    'f', 'a', 'c', 'e', ' ', 't', 'e', 'r', 'r', 'e', 's', 't',
    'r', 'e', '[', '7', ']', ' ', 'e', 't', ' ', 'l', 'e', ' ',
    'd', 'e', 'u', 'x', 'i', 195, 168, 'm', 'e', ' ', 'p', 'a',
    'r', ' ', 's', 'a', ' ', 'z', 'o', 'n', 'e', ' ', 195, 169,
    'c', 'o', 'n', 'o', 'm', 'i', 'q', 'u', 'e', ' ', 'e', 'x',
    'c', 'l', 'u', 's', 'i', 'v', 'e', '[', '8', ']', '.', ' ',
    'E', 'l', 'l', 'e', ' ', 'e', 's', 't', ' ', 'e', 'n', ' ',
    'o', 'u', 't', 'r', 'e', ' ', 'l', 'e', ' ', 't', 'r', 'o',
    'i', 's', 'i', 195, 168, 'm', 'e', ' ', 'p', 'l', 'u', 's',
    ' ', 'g', 'r', 'a', 'n', 'd', ' ', 'p', 'a', 'y', 's', ' ',
    'd', 226, 128, 153, 'E', 'u', 'r', 'o', 'p', 'e', ',', ' ',
    'a', 'p', 'r', 195, 168, 's', ' ', 'l', 'a', ' ', 'R', 'u',
    's', 's', 'i', 'e', ' ', 'e', 't', ' ', 'l', 226, 128, 153,
    'U', 'k', 'r', 'a', 'i', 'n', 'e', ',', ' ', 'd', 'e', 'u',
    'x', 'i', 195, 168, 'm', 'e', ' ', 's', 'i', ' ', 'o', 'n',
    ' ', 'i', 'n', 'c', 'l', 'u', 't', ' ', 'l', 'e', 's', ' ',
    'd', 195, 169, 'p', 'a', 'r', 't', 'e', 'm', 'e', 'n', 't',
    's', ' ', 'u', 'l', 't', 'r', 'a', '-', 'm', 'a', 'r', 'i',
    'n', 's', ',', ' ', 'e', 't', ' ', 'l', 'e', ' ', 'p', 'l',
    'u', 's', ' ', 'g', 'r', 'a', 'n', 'd', ' ', 'd', 'e', ' ',
    'l', 226, 128, 153, 'U', 'n', 'i', 'o', 'n', ' ', 'e', 'u',
    'r', 'o', 'p', 195, 169, 'e', 'n', 'n', 'e', '[', '7', ']',
    '.', ' ', 'S', 'o', 'n', ' ', 't', 'e', 'r', 'r', 'i', 't',
    'o', 'i', 'r', 'e', ' ', 'm', 195, 169, 't', 'r', 'o', 'p',
    'o', 'l', 'i', 't', 'a', 'i', 'n', ' ', 'c', 'o', 'n', 't',
    'i', 'n', 'e', 'n', 't', 'a', 'l', ' ', 's', 226, 128, 153,
    195, 169, 't', 'e', 'n', 'd', ' ', 's', 'u', 'r', ' ', 'e',
    'n', 'v', 'i', 'r', 'o', 'n', ' ', '1', ' ', '0', '0', '0',
    ' ', 'k', 'm', ' ', 'd', 'u', ' ', 'n', 'o', 'r', 'd', ' ',
    'a', 'u', ' ', 's', 'u', 'd', ' ', 'e', 't', ' ', 'd', 226,
    128, 153, 'e', 's', 't', ' ', 'e', 'n', ' ', 'o', 'u', 'e',
    's', 't', '.', ' ', 'L', 226, 128, 153, 195, 169, 't', 'e',
    'n', 'd', 'u', 'e', ' ', 'd', 'e', ' ', 's', 'o', 'n', ' ',
    'l', 'i', 't', 't', 'o', 'r', 'a', 'l', ',', ' ', 'o', 'u',
    't', 'r', 'e', '-', 'm', 'e', 'r', ' ', 'i', 'n', 'c', 'l',
    'u', 's', ',', ' ', 'e', 's', 't', ' ', 'd', 'e', ' ', '8',
    ' ', '2', '4', '5', ' ', 'k', 'm', '[', '9', ']', '.',  13,
     10,  13,  10, 'G', 'r', 'e', 'e', 'k', ':',  13,  10,  13,
     10, 206, 151, ' ', 206, 149, 206, 187, 206, 187, 206, 172,
    206, 180, 206, 177, ' ', '(', 207, 128, 206, 177, 206, 187,
    206, 177, 206, 185, 207, 140, 207, 132, 206, 181, 207, 129,
    206, 177, ':', ' ', 225, 188, 153, 206, 187, 206, 187, 206,
    172, 207, 130, ',', ' ', 206, 181, 207, 128, 206, 175, 207,
    131, 206, 183, 206, 188, 206, 177, ':', ' ', 206, 149, 206,
    187, 206, 187, 206, 183, 206, 189, 206, 185, 206, 186, 206,
    174, ' ', 206, 148, 206, 183, 206, 188, 206, 191, 206, 186,
    207, 129, 206, 177, 207, 132, 206, 175, 206, 177, ')', ' ',
    206, 181, 206, 175, 206, 189, 206, 177, 206, 185, ' ', 207,
    135, 207, 142, 207, 129, 206, 177, ' ', 207, 128, 206, 191,
    207, 133, ' ', 206, 178, 207, 129, 206, 175, 207, 131, 206,
    186, 206, 181, 207, 132, 206, 177, 206, 185, ' ', 207, 131,
    207, 132, 206, 183, ' ', 206, 189, 206, 191, 207, 132, 206,
    185, 206, 191, 206, 177, 206, 189, 206, 177, 207, 132, 206,
    191, 206, 187, 206, 185, 206, 186, 206, 174, ' ', 206, 149,
    207, 133, 207, 129, 207, 142, 207, 128, 206, 183, ',', ' ',
    207, 131, 207, 132, 206, 191, ' ', 206, 189, 206, 191, 207,
    132, 206, 185, 207, 140, 207, 132, 206, 181, 207, 129, 206,
    191, ' ', 206, 172, 206, 186, 207, 129, 206, 191, ' ', 207,
    132, 206, 183, 207, 130, ' ', 206, 146, 206, 177, 206, 187,
    206, 186, 206, 177, 206, 189, 206, 185, 206, 186, 206, 174,
    207, 130, ' ', 207, 135, 206, 181, 207, 129, 207, 131, 206,
    191, 206, 189, 206, 174, 207, 131, 206, 191, 207, 133, ',',
    ' ', 207, 131, 207, 132, 206, 183, 206, 189, ' ', 206, 145,
    206, 189, 206, 177, 207, 132, 206, 191, 206, 187, 206, 185,
    206, 186, 206, 174, ' ', 206, 156, 206, 181, 207, 131, 207,
    140, 206, 179, 206, 181, 206, 185, 206, 191, '.', 206, 160,
    207, 129, 207, 137, 207, 132, 206, 181, 207, 141, 206, 191,
    207, 133, 207, 131, 206, 177, ' ', 207, 132, 206, 183, 207,
    130, ' ', 206, 149, 206, 187, 206, 187, 206, 172, 206, 180,
    206, 191, 207, 130, ' ', 206, 186, 206, 177, 206, 185, ' ',
    206, 188, 206, 181, 206, 179, 206, 177, 206, 187, 207, 141,
    207, 132, 206, 181, 207, 129, 206, 183, ' ', 207, 128, 207,
    140, 206, 187, 206, 183, ' ', 206, 181, 206, 175, 206, 189,
    206, 177, 206, 185, ' ', 206, 183, ' ', 206, 145, 206, 184,
    206, 174, 206, 189, 206, 177, '.',  13,  10,  13,  10, 206,
    163, 207, 133, 206, 189, 206, 191, 207, 129, 206, 181, 207,
    141, 206, 181, 206, 185, ' ', 207, 131, 207, 132, 206, 177,
    ' ', 206, 178, 206, 191, 207, 129, 206, 181, 206, 185, 206,
    191, 206, 180, 207, 133, 207, 132, 206, 185, 206, 186, 206,
    172, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183, 206,
    189, ' ', 206, 145, 206, 187, 206, 178, 206, 177, 206, 189,
    206, 175, 206, 177, ',', ' ', 207, 131, 207, 132, 206, 177,
    ' ', 206, 178, 207, 140, 207, 129, 206, 181, 206, 185, 206,
    177, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183, ' ',
    206, 146, 206, 191, 207, 133, 206, 187, 206, 179, 206, 177,
    207, 129, 206, 175, 206, 177, ' ', 206, 186, 206, 177, 206,
    185, ' ', 207, 132, 206, 183, 206, 189, ' ', 207, 128, 207,
    129, 207, 142, 206, 183, 206, 189, ' ', 206, 147, 206, 185,
    206, 191, 207, 133, 206, 179, 206, 186, 206, 191, 207, 131,
    206, 187, 206, 177, 206, 178, 206, 185, 206, 186, 206, 174,
    ' ', 206, 148, 206, 183, 206, 188, 206, 191, 206, 186, 207,
    129, 206, 177, 207, 132, 206, 175, 206, 177, ' ', 207, 132,
    206, 183, 207, 130, ' ', 206, 156, 206, 177, 206, 186, 206,
    181, 206, 180, 206, 191, 206, 189, 206, 175, 206, 177, 207,
    130, ' ', '(', 207, 128, '.', 206, 147, '.', 206, 148, '.',
    206, 156, '.', ')', ' ', 206, 186, 206, 177, 206, 185, ' ',
    207, 131, 207, 132, 206, 177, ' ', 206, 178, 206, 191, 207,
    129, 206, 181, 206, 185, 206, 191, 206, 177, 206, 189, 206,
    177, 207, 132, 206, 191, 206, 187, 206, 185, 206, 186, 206,
    172, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183, 206,
    189, ' ', 206, 164, 206, 191, 207, 133, 207, 129, 206, 186,
    206, 175, 206, 177, '.', ' ', 206, 146, 207, 129, 206, 173,
    207, 135, 206, 181, 207, 132, 206, 177, 206, 185, ' ', 207,
    131, 207, 132, 206, 177, ' ', 206, 177, 206, 189, 206, 177,
    207, 132, 206, 191, 206, 187, 206, 185, 206, 186, 206, 172,
    ' ', 206, 177, 207, 128, 207, 140, ' ', 207, 132, 206, 191,
    ' ', 206, 145, 206, 185, 206, 179, 206, 177, 206, 175, 206,
    191, ' ', 206, 160, 206, 173, 206, 187, 206, 177, 206, 179,
    206, 191, 207, 130, ',', ' ', 207, 131, 207, 132, 206, 177,
    ' ', 206, 180, 207, 133, 207, 132, 206, 185, 206, 186, 206,
    172, ' ', 206, 177, 207, 128, 207, 140, ' ', 207, 132, 206,
    191, ' ', 206, 153, 207, 140, 206, 189, 206, 185, 206, 191,
    ' ', 206, 186, 206, 177, 206, 185, ' ', 206, 189, 207, 140,
    207, 132, 206, 185, 206, 177, ' ', 206, 177, 207, 128, 207,
    140, ' ', 207, 132, 206, 183, ' ', 206, 156, 206, 181, 207,
    131, 207, 140, 206, 179, 206, 181, 206, 185, 206, 191, ' ',
    206, 152, 206, 172, 206, 187, 206, 177, 207, 131, 207, 131,
    206, 177, '.', 206, 151, ' ', 206, 149, 206, 187, 206, 187,
    206, 172, 206, 180, 206, 177, ' ', 206, 186, 206, 177, 207,
    132, 206, 173, 207, 135, 206, 181, 206, 185, ' ', 207, 132,
    206, 183, 206, 189, ' ', '1', '1', 206, 183, ' ', 206, 184,
    206, 173, 207, 131, 206, 183, ' ', 207, 131, 207, 132, 206,
    185, 207, 130, ' ', 207, 135, 207, 142, 207, 129, 206, 181,
    207, 130, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183,
    ' ', 206, 188, 206, 181, 206, 179, 206, 177, 206, 187, 207,
    141, 207, 132, 206, 181, 207, 129, 206, 183, ' ', 206, 177,
    206, 186, 207, 132, 206, 191, 206, 179, 207, 129, 206, 177,
    206, 188, 206, 188, 206, 174, ' ', 207, 131, 207, 132, 206,
    177, ' ', '1', '3', '.', '6', '7', '6', ' ', 207, 135, 206,
    185, 206, 187, 206, 185, 207, 140, 206, 188, 206, 181, 207,
    132, 207, 129, 206, 177, ' ', 206, 186, 206, 177, 206, 184,
    207, 142, 207, 130, ' ', 206, 181, 207, 135, 206, 181, 206,
    185, ' ', 207, 128, 206, 191, 206, 187, 206, 187, 206, 172,
    ' ', 206, 189, 206, 183, 207, 131, 206, 185, 206, 172, ' ',
    '(', 207, 128, 206, 181, 207, 129, 206, 175, 207, 128, 206,
    191, 207, 133, ' ', '1', '.', '4', '0', '0', ',', ' ', 206,
    181, 206, 186, 207, 132, 207, 137, 206, 189, ' ', 206, 191,
    207, 128, 206, 191, 206, 175, 207, 137, 206, 189, ' ', 207,
    132, 206, 177, ' ', '2', '2', '7', ' ', 206, 186, 206, 177,
    207, 132, 206, 191, 206, 185, 206, 186, 206, 191, 207, 133,
    206, 189, 207, 132, 206, 177, 206, 185, ')', ',', ' ', 207,
    131, 207, 133, 206, 188, 207, 128, 206, 181, 207, 129, 206,
    185, 206, 187, 206, 177, 206, 188, 206, 178, 206, 177, 206,
    189, 206, 191, 206, 188, 206, 173, 206, 189, 207, 137, 206,
    189, ' ', 207, 132, 206, 183, 207, 130, ' ', 206, 154, 207,
    129, 206, 183, 207, 132, 206, 183, 207, 130, ',', ' ', 207,
    132, 207, 137, 206, 189, ' ', 206, 148, 207, 137, 206, 180,
    206, 181, 206, 186, 206, 177, 206, 189, 206, 174, 207, 131,
    207, 137, 206, 189, ',', ' ', 207, 132, 207, 137, 206, 189,
    ' ', 206, 154, 207, 133, 206, 186, 206, 187, 206, 172, 206,
    180, 207, 137, 206, 189, ',', ' ', 207, 132, 207, 137, 206,
    189, ' ', 206, 149, 207, 128, 207, 132, 206, 177, 206, 189,
    206, 174, 207, 131, 207, 137, 206, 189, ' ', 206, 186, 206,
    177, 206, 185, ' ', 207, 128, 206, 191, 206, 187, 206, 187,
    207, 142, 206, 189, ' ', 206, 172, 206, 187, 206, 187, 207,
    137, 206, 189, '.', 206, 164, 206, 191, ' ', 207, 136, 206,
    183, 206, 187, 207, 140, 207, 132, 206, 181, 207, 129, 206,
    191, ' ', 206, 178, 206, 191, 207, 133, 206, 189, 207, 140,
    ' ', 206, 181, 206, 175, 206, 189, 206, 177, 206, 185, ' ',
    206, 191, ' ', 206, 140, 206, 187, 207, 133, 206, 188, 207,
    128, 206, 191, 207, 130, ' ', 206, 186, 206, 177, 206, 185,
    ' ', 207, 132, 206, 191, ' ', 206, 188, 206, 181, 206, 179,
    206, 177, 206, 187, 207, 141, 207, 132, 206, 181, 207, 129,
    206, 191, ' ', 207, 128, 206, 191, 207, 132, 206, 172, 206,
    188, 206, 185, ' ', 206, 191, ' ', 206, 145, 206, 187, 206,
    185, 206, 172, 206, 186, 206, 188, 206, 191, 206, 189, 206,
    177, 207, 130, '.',  13,  10,  13,  10, 206, 136, 207, 135,
    206, 181, 206, 185, ' ', 206, 188, 206, 177, 206, 186, 207,
    129, 206, 172, ' ', 206, 186, 206, 177, 206, 185, ' ', 207,
    128, 206, 187, 206, 191, 207, 141, 207, 131, 206, 185, 206,
    177, ' ', 206, 185, 207, 131, 207, 132, 206, 191, 207, 129,
    206, 175, 206, 177, ' ', 206, 186, 206, 177, 207, 132, 206,
    172, ' ', 207, 132, 206, 183, 206, 189, ' ', 206, 191, 207,
    128, 206, 191, 206, 175, 206, 177, ' ', 206, 172, 207, 131,
    206, 186, 206, 183, 207, 131, 206, 181, ' ', 206, 188, 206,
    181, 206, 179, 206, 172, 206, 187, 206, 183, ' ', 207, 128,
    206, 191, 206, 187, 206, 185, 207, 132, 206, 185, 207, 131,
    206, 188, 206, 185, 206, 186, 206, 174, ' ', 206, 181, 207,
    128, 206, 175, 206, 180, 207, 129, 206, 177, 207, 131, 206,
    183, ' ', 207, 131, 206, 181, ' ', 207, 132, 207, 129, 206,
    181, 206, 185, 207, 130, ' ', 206, 183, 207, 128, 206, 181,
    206, 175, 207, 129, 206, 191, 207, 133, 207, 130, '.', 206,
    149, 206, 180, 207, 142, ' ', 206, 179, 206, 181, 206, 189,
    206, 189, 206, 174, 206, 184, 206, 183, 206, 186, 206, 181,
    ' ', 206, 183, ' ', 206, 180, 206, 183, 206, 188, 206, 191,
    206, 186, 207, 129, 206, 177, 207, 132, 206, 175, 206, 177,
    ' ', 206, 186, 206, 177, 206, 185, ' ', 206, 183, ' ', 207,
    134, 206, 185, 206, 187, 206, 191, 207, 131, 206, 191, 207,
    134, 206, 175, 206, 177, '.', 206, 145, 206, 186, 207, 140,
    206, 188, 206, 188, 206, 177, ' ', 206, 183, ' ', 206, 149,
    206, 187, 206, 187, 206, 172, 206, 180, 206, 177, ' ', 206,
    181, 206, 175, 206, 189, 206, 177, 206, 185, ' ', 206, 191,
    ' ', 207, 132, 207, 140, 207, 128, 206, 191, 207, 130, ' ',
    206, 179, 206, 173, 206, 189, 206, 189, 206, 183, 207, 131,
    206, 183, 207, 130, ' ', 207, 132, 207, 137, 206, 189, ' ',
    206, 159, 206, 187, 207, 133, 206, 188, 207, 128, 206, 185,
    206, 177, 206, 186, 207, 142, 206, 189, ' ', 206, 145, 206,
    179, 207, 142, 206, 189, 207, 137, 206, 189, ',', 207, 132,
    206, 191, 207, 133, ' ', 206, 180, 207, 129, 206, 172, 206,
    188, 206, 177, 207, 132, 206, 191, 207, 130, ',', ' ', 207,
    132, 206, 183, 207, 130, ' ', 207, 132, 207, 129, 206, 177,
    206, 179, 207, 137, 206, 180, 206, 175, 206, 177, 207, 130,
    ' ', 206, 186, 206, 177, 206, 185, ' ', 207, 132, 206, 183,
    207, 130, ' ', 206, 186, 207, 137, 206, 188, 206, 188, 207,
    137, 206, 180, 206, 175, 206, 177, 207, 130, ' ', '.',  13,
     10,  13,  10, 206, 151, ' ', 206, 149, 206, 187, 206, 187,
    206, 172, 206, 180, 206, 177, ' ', 206, 181, 206, 175, 206,
    189, 206, 177, 206, 185, ' ', 206, 188, 206, 173, 206, 187,
    206, 191, 207, 130, ' ', 207, 132, 207, 137, 206, 189, ' ',
    206, 149, 207, 133, 207, 129, 207, 137, 207, 128, 206, 177,
    207, 138, 206, 186, 207, 142, 206, 189, ' ', 206, 154, 206,
    191, 206, 185, 206, 189, 206, 191, 207, 132, 206, 174, 207,
    132, 207, 137, 206, 189, '/', 206, 149, 207, 133, 207, 129,
    207, 137, 207, 128, 206, 177, 207, 138, 206, 186, 206, 174,
    207, 130, ' ', 206, 136, 206, 189, 207, 137, 207, 131, 206,
    183, 207, 130, ' ', 206, 177, 207, 128, 207, 140, ' ', 207,
    132, 206, 191, ' ', '1', '9', '8', '1', ',', ' ', 207, 132,
    206, 183, 207, 130, ' ', 206, 149, 207, 133, 207, 129, 207,
    137, 206, 182, 207, 142, 206, 189, 206, 183, 207, 130, ' ',
    206, 177, 207, 128, 207, 140, ' ', 207, 132, 206, 191, ' ',
    '2', '0', '0', '1', ',', ' ', 207, 132, 206, 191, 207, 133,
    ' ', 206, 157, 206, 145, 206, 164, 206, 159, ' ', 206, 177,
    207, 128, 207, 140, ' ', 207, 132, 206, 191, ' ', '1', '9',
    '5', '2', ' ', 206, 186, 206, 177, 206, 185, ' ', 206, 185,
    206, 180, 207, 129, 207, 133, 207, 132, 206, 185, 206, 186,
    207, 140, ' ', 206, 188, 206, 173, 206, 187, 206, 191, 207,
    130, ' ', 207, 132, 206, 191, 207, 133, ' ', 206, 159, 206,
    151, 206, 149, ' ', '(', '1', '9', '4', '5', ')', '.', ' ',
    206, 151, ' ', 206, 149, 206, 187, 206, 187, 206, 172, 206,
    180, 206, 177, ' ', 206, 181, 206, 175, 206, 189, 206, 177,
    206, 185, ' ', 206, 188, 206, 185, 206, 177, ' ', 206, 177,
    206, 189, 206, 181, 207, 128, 207, 132, 207, 133, 206, 179,
    206, 188, 206, 173, 206, 189, 206, 183, ' ', 207, 135, 207,
    142, 207, 129, 206, 177, ' ', 206, 188, 206, 181, ' ', 207,
    133, 207, 136, 206, 183, 206, 187, 207, 140, ' ', 206, 186,
    206, 177, 207, 132, 206, 172, ' ', 206, 186, 206, 181, 207,
    134, 206, 177, 206, 187, 206, 174, 206, 189, ' ', 206, 181,
    206, 185, 207, 131, 207, 140, 206, 180, 206, 183, 206, 188,
    206, 177, ' ', 206, 186, 206, 177, 206, 185, ' ', 207, 128,
    206, 191, 206, 187, 207, 141, ' ', 207, 133, 207, 136, 206,
    183, 206, 187, 207, 140, ' ', 206, 180, 206, 181, 206, 175,
    206, 186, 207, 132, 206, 183, ' ', 206, 177, 206, 189, 206,
    184, 207, 129, 207, 142, 207, 128, 206, 185, 206, 189, 206,
    183, 207, 130, ' ', 206, 177, 206, 189, 206, 172, 207, 128,
    207, 132, 207, 133, 206, 190, 206, 183, 207, 130, '.', ' ',
    206, 154, 206, 177, 207, 132, 206, 173, 207, 135, 206, 181,
    206, 185, ' ', 207, 132, 206, 183, 206, 189, ' ', '2', '2',
    206, 183, ' ', 206, 186, 206, 177, 206, 187, 207, 141, 207,
    132, 206, 181, 207, 129, 206, 183, ' ', 207, 128, 206, 191,
    206, 185, 207, 140, 207, 132, 206, 183, 207, 132, 206, 177,
    ' ', 206, 182, 207, 137, 206, 174, 207, 130, ' ', 207, 131,
    207, 132, 206, 191, 206, 189, ' ', 206, 186, 207, 140, 207,
    131, 206, 188, 206, 191, '.', '[', '4', ']',  13,  10,  13,
     10, 206, 151, ' ', 206, 149, 206, 187, 206, 187, 206, 172,
    206, 180, 206, 177, ' ', '(', 207, 128, 206, 177, 206, 187,
    206, 177, 206, 185, 207, 140, 207, 132, 206, 181, 207, 129,
    206, 177, ':', ' ', 225, 188, 153, 206, 187, 206, 187, 206,
    172, 207, 130, ',', ' ', 206, 181, 207, 128, 206, 175, 207,
    131, 206, 183, 206, 188, 206, 177, ':', ' ', 206, 149, 206,
    187, 206, 187, 206, 183, 206, 189, 206, 185, 206, 186, 206,
    174, ' ', 206, 148, 206, 183, 206, 188, 206, 191, 206, 186,
    207, 129, 206, 177, 207, 132, 206, 175, 206, 177, ')', ' ',
    206, 181, 206, 175, 206, 189, 206, 177, 206, 185, ' ', 207,
    135, 207, 142, 207, 129, 206, 177, ' ', 207, 128, 206, 191,
    207, 133, ' ', 206, 178, 207, 129, 206, 175, 207, 131, 206,
    186, 206, 181, 207, 132, 206, 177, 206, 185, ' ', 207, 131,
    207, 132, 206, 183, ' ', 206, 189, 206, 191, 207, 132, 206,
    185, 206, 191, 206, 177, 206, 189, 206, 177, 207, 132, 206,
    191, 206, 187, 206, 185, 206, 186, 206, 174, ' ', 206, 149,
    207, 133, 207, 129, 207, 142, 207, 128, 206, 183, ',', ' ',
    207, 131, 207, 132, 206, 191, ' ', 206, 189, 206, 191, 207,
    132, 206, 185, 207, 140, 207, 132, 206, 181, 207, 129, 206,
    191, ' ', 206, 172, 206, 186, 207, 129, 206, 191, ' ', 207,
    132, 206, 183, 207, 130, ' ', 206, 146, 206, 177, 206, 187,
    206, 186, 206, 177, 206, 189, 206, 185, 206, 186, 206, 174,
    207, 130, ' ', 207, 135, 206, 181, 207, 129, 207, 131, 206,
    191, 206, 189, 206, 174, 207, 131, 206, 191, 207, 133, ',',
    ' ', 207, 131, 207, 132, 206, 183, 206, 189, ' ', 206, 145,
    206, 189, 206, 177, 207, 132, 206, 191, 206, 187, 206, 185,
    206, 186, 206, 174, ' ', 206, 156, 206, 181, 207, 131, 207,
    140, 206, 179, 206, 181, 206, 185, 206, 191, '.', 206, 160,
    207, 129, 207, 137, 207, 132, 206, 181, 207, 141, 206, 191,
    207, 133, 207, 131, 206, 177, ' ', 207, 132, 206, 183, 207,
    130, ' ', 206, 149, 206, 187, 206, 187, 206, 172, 206, 180,
    206, 191, 207, 130, ' ', 206, 186, 206, 177, 206, 185, ' ',
    206, 188, 206, 181, 206, 179, 206, 177, 206, 187, 207, 141,
    207, 132, 206, 181, 207, 129, 206, 183, ' ', 207, 128, 207,
    140, 206, 187, 206, 183, ' ', 206, 181, 206, 175, 206, 189,
    206, 177, 206, 185, ' ', 206, 183, ' ', 206, 145, 206, 184,
    206, 174, 206, 189, 206, 177, '.',  13,  10,  13,  10, 206,
    163, 207, 133, 206, 189, 206, 191, 207, 129, 206, 181, 207,
    141, 206, 181, 206, 185, ' ', 207, 131, 207, 132, 206, 177,
    ' ', 206, 178, 206, 191, 207, 129, 206, 181, 206, 185, 206,
    191, 206, 180, 207, 133, 207, 132, 206, 185, 206, 186, 206,
    172, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183, 206,
    189, ' ', 206, 145, 206, 187, 206, 178, 206, 177, 206, 189,
    206, 175, 206, 177, ',', ' ', 207, 131, 207, 132, 206, 177,
    ' ', 206, 178, 207, 140, 207, 129, 206, 181, 206, 185, 206,
    177, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183, ' ',
    206, 146, 206, 191, 207, 133, 206, 187, 206, 179, 206, 177,
    207, 129, 206, 175, 206, 177, ' ', 206, 186, 206, 177, 206,
    185, ' ', 207, 132, 206, 183, 206, 189, ' ', 207, 128, 207,
    129, 207, 142, 206, 183, 206, 189, ' ', 206, 147, 206, 185,
    206, 191, 207, 133, 206, 179, 206, 186, 206, 191, 207, 131,
    206, 187, 206, 177, 206, 178, 206, 185, 206, 186, 206, 174,
    ' ', 206, 148, 206, 183, 206, 188, 206, 191, 206, 186, 207,
    129, 206, 177, 207, 132, 206, 175, 206, 177, ' ', 207, 132,
    206, 183, 207, 130, ' ', 206, 156, 206, 177, 206, 186, 206,
    181, 206, 180, 206, 191, 206, 189, 206, 175, 206, 177, 207,
    130, ' ', '(', 207, 128, '.', 206, 147, '.', 206, 148, '.',
    206, 156, '.', ')', ' ', 206, 186, 206, 177, 206, 185, ' ',
    207, 131, 207, 132, 206, 177, ' ', 206, 178, 206, 191, 207,
    129, 206, 181, 206, 185, 206, 191, 206, 177, 206, 189, 206,
    177, 207, 132, 206, 191, 206, 187, 206, 185, 206, 186, 206,
    172, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183, 206,
    189, ' ', 206, 164, 206, 191, 207, 133, 207, 129, 206, 186,
    206, 175, 206, 177, '.', ' ', 206, 146, 207, 129, 206, 173,
    207, 135, 206, 181, 207, 132, 206, 177, 206, 185, ' ', 207,
    131, 207, 132, 206, 177, ' ', 206, 177, 206, 189, 206, 177,
    207, 132, 206, 191, 206, 187, 206, 185, 206, 186, 206, 172,
    ' ', 206, 177, 207, 128, 207, 140, ' ', 207, 132, 206, 191,
    ' ', 206, 145, 206, 185, 206, 179, 206, 177, 206, 175, 206,
    191, ' ', 206, 160, 206, 173, 206, 187, 206, 177, 206, 179,
    206, 191, 207, 130, ',', ' ', 207, 131, 207, 132, 206, 177,
    ' ', 206, 180, 207, 133, 207, 132, 206, 185, 206, 186, 206,
    172, ' ', 206, 177, 207, 128, 207, 140, ' ', 207, 132, 206,
    191, ' ', 206, 153, 207, 140, 206, 189, 206, 185, 206, 191,
    ' ', 206, 186, 206, 177, 206, 185, ' ', 206, 189, 207, 140,
    207, 132, 206, 185, 206, 177, ' ', 206, 177, 207, 128, 207,
    140, ' ', 207, 132, 206, 183, ' ', 206, 156, 206, 181, 207,
    131, 207, 140, 206, 179, 206, 181, 206, 185, 206, 191, ' ',
    206, 152, 206, 172, 206, 187, 206, 177, 207, 131, 207, 131,
    206, 177, '.', 206, 151, ' ', 206, 149, 206, 187, 206, 187,
    206, 172, 206, 180, 206, 177, ' ', 206, 186, 206, 177, 207,
    132, 206, 173, 207, 135, 206, 181, 206, 185, ' ', 207, 132,
    206, 183, 206, 189, ' ', '1', '1', 206, 183, ' ', 206, 184,
    206, 173, 207, 131, 206, 183, ' ', 207, 131, 207, 132, 206,
    185, 207, 130, ' ', 207, 135, 207, 142, 207, 129, 206, 181,
    207, 130, ' ', 206, 188, 206, 181, ' ', 207, 132, 206, 183,
    ' ', 206, 188, 206, 181, 206, 179, 206, 177, 206, 187, 207,
    141, 207, 132, 206, 181, 207, 129, 206, 183, ' ', 206, 177,
    206, 186, 207, 132, 206, 191, 206, 179, 207, 129, 206, 177,
    206, 188, 206, 188, 206, 174, ' ', 207, 131, 207, 132, 206,
    177, ' ', '1', '3', '.', '6', '7', '6', ' ', 207, 135, 206,
    185, 206, 187, 206, 185, 207, 140, 206, 188, 206, 181, 207,
    132, 207, 129, 206, 177, ' ', 206, 186, 206, 177, 206, 184,
    207, 142, 207, 130, ' ', 206, 181, 207, 135, 206, 181, 206,
    185, ' ', 207, 128, 206, 191, 206, 187, 206, 187, 206, 172,
    ' ', 206, 189, 206, 183, 207, 131, 206, 185, 206, 172, ' ',
    '(', 207, 128, 206, 181, 207, 129, 206, 175, 207, 128, 206,
    191, 207, 133, ' ', '1', '.', '4', '0', '0', ',', ' ', 206,
    181, 206, 186, 207, 132, 207, 137, 206, 189, ' ', 206, 191,
    207, 128, 206, 191, 206, 175, 207, 137, 206, 189, ' ', 207,
    132, 206, 177, ' ', '2', '2', '7', ' ', 206, 186, 206, 177,
    207, 132, 206, 191, 206, 185, 206, 186, 206, 191, 207, 133,
    206, 189, 207, 132, 206, 177, 206, 185, ')', ',', ' ', 207,
    131, 207, 133, 206, 188, 207, 128, 206, 181, 207, 129, 206,
    185, 206, 187, 206, 177, 206, 188, 206, 178, 206, 177, 206,
    189, 206, 191, 206, 188, 206, 173, 206, 189, 207, 137, 206,
    189, ' ', 207, 132, 206, 183, 207, 130, ' ', 206, 154, 207,
    129, 206, 183, 207, 132, 206, 183, 207, 130, ',', ' ', 207,
    132, 207, 137, 206, 189, ' ', 206, 148, 207, 137, 206, 180,
    206, 181, 206, 186, 206, 177, 206, 189, 206, 174, 207, 131,
    207, 137, 206, 189, ',', ' ', 207, 132, 207, 137, 206, 189,
    ' ', 206, 154, 207, 133, 206, 186, 206, 187, 206, 172, 206,
    180, 207, 137, 206, 189, ',', ' ', 207, 132, 207, 137, 206,
    189, ' ', 206, 149, 207, 128, 207, 132, 206, 177, 206, 189,
    206, 174, 207, 131, 207, 137, 206, 189, ' ', 206, 186, 206,
    177, 206, 185, ' ', 207, 128, 206, 191, 206, 187, 206, 187,
    207, 142, 206, 189, ' ', 206, 172, 206, 187, 206, 187, 207,
    137, 206, 189, '.', 206, 164, 206, 191, ' ', 207, 136, 206,
    183, 206, 187, 207, 140, 207, 132, 206, 181, 207, 129, 206,
    191, ' ', 206, 178, 206, 191, 207, 133, 206, 189, 207, 140,
    ' ', 206, 181, 206, 175, 206, 189, 206, 177, 206, 185, ' ',
    206, 191, ' ', 206, 140, 206, 187, 207, 133, 206, 188, 207,
    128, 206, 191, 207, 130, ' ', 206, 186, 206, 177, 206, 185,
    ' ', 207, 132, 206, 191, ' ', 206, 188, 206, 181, 206, 179,
    206, 177, 206, 187, 207, 141, 207, 132, 206, 181, 207, 129,
    206, 191, ' ', 207, 128, 206, 191, 207, 132, 206, 172, 206,
    188, 206, 185, ' ', 206, 191, ' ', 206, 145, 206, 187, 206,
    185, 206, 172, 206, 186, 206, 188, 206, 191, 206, 189, 206,
    177, 207, 130, '.',  13,  10,  13,  10, 206, 136, 207, 135,
    206, 181, 206, 185, ' ', 206, 188, 206, 177, 206, 186, 207,
    129, 206, 172, ' ', 206, 186, 206, 177, 206, 185, ' ', 207,
    128, 206, 187, 206, 191, 207, 141, 207, 131, 206, 185, 206,
    177, ' ', 206, 185, 207, 131, 207, 132, 206, 191, 207, 129,
    206, 175, 206, 177, ' ', 206, 186, 206, 177, 207, 132, 206,
    172, ' ', 207, 132, 206, 183, 206, 189, ' ', 206, 191, 207,
    128, 206, 191, 206, 175, 206, 177, ' ', 206, 172, 207, 131,
    206, 186, 206, 183, 207, 131, 206, 181, ' ', 206, 188, 206,
    181, 206, 179, 206, 172, 206, 187, 206, 183, ' ', 207, 128,
    206, 191, 206, 187, 206, 185, 207, 132, 206, 185, 207, 131,
    206, 188, 206, 185, 206, 186, 206, 174, ' ', 206, 181, 207,
    128, 206, 175, 206, 180, 207, 129, 206, 177, 207, 131, 206,
    183, ' ', 207, 131, 206, 181, ' ', 207, 132, 207, 129, 206,
    181, 206, 185, 207, 130, ' ', 206, 183, 207, 128, 206, 181,
    206, 175, 207, 129, 206, 191, 207, 133, 207, 130, '.', 206,
    149, 206, 180, 207, 142, ' ', 206, 179, 206, 181, 206, 189,
    206, 189, 206, 174, 206, 184, 206, 183, 206, 186, 206, 181,
    ' ', 206, 183, ' ', 206, 180, 206, 183, 206, 188, 206, 191,
    206, 186, 207, 129, 206, 177, 207, 132, 206, 175, 206, 177,
    ' ', 206, 186, 206, 177, 206, 185, ' ', 206, 183, ' ', 207,
    134, 206, 185, 206, 187, 206, 191, 207, 131, 206, 191, 207,
    134, 206, 175, 206, 177, '.', 206, 145, 206, 186, 207, 140,
    206, 188, 206, 188, 206, 177, ' ', 206, 183, ' ', 206, 149,
    206, 187, 206, 187, 206, 172, 206, 180, 206, 177, ' ', 206,
    181, 206, 175, 206, 189, 206, 177, 206, 185, ' ', 206, 191,
    ' ', 207, 132, 207, 140, 207, 128, 206, 191, 207, 130, ' ',
    206, 179, 206, 173, 206, 189, 206, 189, 206, 183, 207, 131,
    206, 183, 207, 130, ' ', 207, 132, 207, 137, 206, 189, ' ',
    206, 159, 206, 187, 207, 133, 206, 188, 207, 128, 206, 185,
    206, 177, 206, 186, 207, 142, 206, 189, ' ', 206, 145, 206,
    179, 207, 142, 206, 189, 207, 137, 206, 189, ',', 207, 132,
    206, 191, 207, 133, ' ', 206, 180, 207, 129, 206, 172, 206,
    188, 206, 177, 207, 132, 206, 191, 207, 130, ',', ' ', 207,
    132, 206, 183, 207, 130, ' ', 207, 132, 207, 129, 206, 177,
    206, 179, 207, 137, 206, 180, 206, 175, 206, 177, 207, 130,
    ' ', 206, 186, 206, 177, 206, 185, ' ', 207, 132, 206, 183,
    207, 130, ' ', 206, 186, 207, 137, 206, 188, 206, 188, 207,
    137, 206, 180, 206, 175, 206, 177, 207, 130, ' ', '.',  13,
     10,  13,  10, 206, 151, ' ', 206, 149, 206, 187, 206, 187,
    206, 172, 206, 180, 206, 177, ' ', 206, 181, 206, 175, 206,
    189, 206, 177, 206, 185, ' ', 206, 188, 206, 173, 206, 187,
    206, 191, 207, 130, ' ', 207, 132, 207, 137, 206, 189, ' ',
    206, 149, 207, 133, 207, 129, 207, 137, 207, 128, 206, 177,
    207, 138, 206, 186, 207, 142, 206, 189, ' ', 206, 154, 206,
    191, 206, 185, 206, 189, 206, 191, 207, 132, 206, 174, 207,
    132, 207, 137, 206, 189, '/', 206, 149, 207, 133, 207, 129,
    207, 137, 207, 128, 206, 177, 207, 138, 206, 186, 206, 174,
    207, 130, ' ', 206, 136, 206, 189, 207, 137, 207, 131, 206,
    183, 207, 130, ' ', 206, 177, 207, 128, 207, 140, ' ', 207,
    132, 206, 191, ' ', '1', '9', '8', '1', ',', ' ', 207, 132,
    206, 183, 207, 130, ' ', 206, 149, 207, 133, 207, 129, 207,
    137, 206, 182, 207, 142, 206, 189, 206, 183, 207, 130, ' ',
    206, 177, 207, 128, 207, 140, ' ', 207, 132, 206, 191, ' ',
    '2', '0', '0', '1', ',', ' ', 207, 132, 206, 191, 207, 133,
    ' ', 206, 157, 206, 145, 206, 164, 206, 159, ' ', 206, 177,
    207, 128, 207, 140, ' ', 207, 132, 206, 191, ' ', '1', '9',
    '5', '2', ' ', 206, 186, 206, 177, 206, 185, ' ', 206, 185,
    206, 180, 207, 129, 207, 133, 207, 132, 206, 185, 206, 186,
    207, 140, ' ', 206, 188, 206, 173, 206, 187, 206, 191, 207,
    130, ' ', 207, 132, 206, 191, 207, 133, ' ', 206, 159, 206,
    151, 206, 149, ' ', '(', '1', '9', '4', '5', ')', '.', ' ',
    206, 151, ' ', 206, 149, 206, 187, 206, 187, 206, 172, 206,
    180, 206, 177, ' ', 206, 181, 206, 175, 206, 189, 206, 177,
    206, 185, ' ', 206, 188, 206, 185, 206, 177, ' ', 206, 177,
    206, 189, 206, 181, 207, 128, 207, 132, 207, 133, 206, 179,
    206, 188, 206, 173, 206, 189, 206, 183, ' ', 207, 135, 207,
    142, 207, 129, 206, 177, ' ', 206, 188, 206, 181, ' ', 207,
    133, 207, 136, 206, 183, 206, 187, 207, 140, ' ', 206, 186,
    206, 177, 207, 132, 206, 172, ' ', 206, 186, 206, 181, 207,
    134, 206, 177, 206, 187, 206, 174, 206, 189, ' ', 206, 181,
    206, 185, 207, 131, 207, 140, 206, 180, 206, 183, 206, 188,
    206, 177, ' ', 206, 186, 206, 177, 206, 185, ' ', 207, 128,
    206, 191, 206, 187, 207, 141, ' ', 207, 133, 207, 136, 206,
    183, 206, 187, 207, 140, ' ', 206, 180, 206, 181, 206, 175,
    206, 186, 207, 132, 206, 183, ' ', 206, 177, 206, 189, 206,
    184, 207, 129, 207, 142, 207, 128, 206, 185, 206, 189, 206,
    183, 207, 130, ' ', 206, 177, 206, 189, 206, 172, 207, 128,
    207, 132, 207, 133, 206, 190, 206, 183, 207, 130, '.', ' ',
    206, 154, 206, 177, 207, 132, 206, 173, 207, 135, 206, 181,
    206, 185, ' ', 207, 132, 206, 183, 206, 189, ' ', '2', '2',
    206, 183, ' ', 206, 186, 206, 177, 206, 187, 207, 141, 207,
    132, 206, 181, 207, 129, 206, 183, ' ', 207, 128, 206, 191,
    206, 185, 207, 140, 207, 132, 206, 183, 207, 132, 206, 177,
    ' ', 206, 182, 207, 137, 206, 174, 207, 130, ' ', 207, 131,
    207, 132, 206, 191, 206, 189, ' ', 206, 186, 207, 140, 207,
    131, 206, 188, 206, 191, '.', '[', '4', ']',  13,  10,  13,
     10, 'R', 'a', 'n', 'd', 'o', 'm', ' ', 'Q', 'u', 'a', 'd',
    ' ', 'V', 'a', 'l', 'u', 'e', 's',  13,  10, 240, 144, 128,
    128, 240, 152, 166, 171, 240, 158, 187, 174, 240, 154, 170,
    170, 240, 154, 132, 163, 240, 155, 132, 163, 243, 187, 174,
    187, 244, 128, 128, 128, 243, 174, 187, 174, 242, 187, 174,
    187,  13,  10,   0
};
const char * const charUtf8MultiLang =
                                 reinterpret_cast<const char *>(utf8MultiLang);

// ============================================================================
//                             Padded String Ref
// ============================================================================

namespace {

class PaddedStringRef {
    // This 'class' is initialized by a string (in either of two forms) and the
    // only way to read it is via an implicit conversion to a
    // 'bslstl::StringRef'.  The important quality is that while the string
    // reference converted to will represent the string passed at construction,
    // it will NOT be null terminated, to test functions that take string refs
    // as args, to verify they aren't relying on the input being 0-terminated
    // at the right place.

    // DATA
    bsl::string  d_str;

  public:
    // CREATORS
    explicit
    PaddedStringRef(const char *zStr)
    : d_str()
        // Create a 'PaddedStringRef' referring to an internal copy of the
        // specified null-terminated 'zStr'.
    {
        bsl::size_t len = bsl::strlen(zStr);
        d_str.reserve(len + 4);
        d_str.assign(bslstl::StringRef(zStr, zStr + len));
        d_str += "woof";
    }

    explicit
    PaddedStringRef(const bsl::string& str)
    : d_str()
        // Create a 'PaddedStringRef' referring to an internal copy of the
        // specified 'str'.
    {
        d_str.reserve(str.length() + 4);
        d_str = str;
        d_str += "woof";
    }

    // ACCESSORS
    operator bslstl::StringRef() const
        // Implicit conversion to a string ref which will refer to a copy of
        // the string passed to the c'tor.
    {
        return bslstl::StringRef(d_str.data(), (int) d_str.length() - 4);
    }
};

}  // close unnamed namespace

// ----------------------------------------------------------------------------
// Encode a 4-byte UTF-8 value, print as a sequence of decimal 'int' values.
// ----------------------------------------------------------------------------

char *decodeFourByteUtf8String(char *outBuf, unsigned val)
    // Translate the specified 'val' to UTF-8 to be written to the specified
    // 'outBuf'.  The behavior is undefined unless 4 bytes are available in
    // 'outBuf', and unless the value is appropriate to be encoded in 4 bytes
    // of UTF-8.
{
    ASSERT(0 == (val & ~((1 << 21) - 1)));
    ASSERT(0 != (val & ~((1 << 16) - 1)));

    outBuf[0] = (char) (((val &  (7 << 18)) >> 18) | 0xf0);
    outBuf[1] = (char) (((val & (63 << 12)) >> 12) | 0x80);
    outBuf[2] = (char) (((val & (63 <<  6)) >>  6) | 0x80);
    outBuf[3] = (char) (((val &  63       )      ) | 0x80);

    return outBuf + 4;
}

char *decodeThreeByteUtf8String(char *outBuf, unsigned val)
    // Translate the specified 'val' to UTF-8 to be written to the specified
    // 'outBuf'.  The behavior is undefined unless 3 bytes are available in
    // 'outBuf', and unless the value is appropriate to be encoded in 3 bytes
    // of UTF-8.
{
    ASSERT(0 == (val & ~((1 << 16) - 1)));
    ASSERT(0 != (val & ~((1 << 11) - 1)));

    outBuf[0] = (char) (((val & (15 << 12)) >> 12) | 0xe0);
    outBuf[1] = (char) (((val & (63 <<  6)) >>  6) | 0x80);
    outBuf[2] = (char) (((val &  63       )      ) | 0x80);

    return outBuf + 3;
}

char *decodeTwoByteUtf8String(char *outBuf, unsigned val)
    // Translate the specified 'val' to UTF-8 to be written to the specified
    // 'outBuf'.  The behavior is undefined unless 2 bytes are available in
    // 'outBuf', and unless the value is appropriate to be encoded in 2 bytes
    // of UTF-8.
{
    ASSERT(0 == (val & ~((1 << 11) - 1)));
    ASSERT(0 != (val & ~((1 <<  7) - 1)));

    outBuf[0] = (char) (((val & (31 <<  6)) >>  6) | 0xc0);
    outBuf[1] = (char) (((val &  63       )      ) | 0x80);

    return outBuf + 2;
}

char *decodeOneByteUtf8String(char *outBuf, unsigned val)
    // Translate the specified 'val' to UTF-8 to be written to the specified
    // 'outBuf'.  The behavior is undefined unless 1 byte is available in
    // 'outBuf', and unless the value is appropriate to be encoded in 1 byte of
    // UTF-8.
{
    ASSERT(0 == (val & ~((1 << 7) - 1)));
    ASSERT(0 !=  val);

    *outBuf = (char) val;

    return outBuf + 1;
}

char *decodeUtf32(char *outBuf, unsigned val)
{
    if      (val < 0x80) {
        return decodeOneByteUtf8String(  outBuf, val);                // RETURN
    }
    else if (val < (1 << 11)) {
        return decodeTwoByteUtf8String(  outBuf, val);                // RETURN
    }
    else if (val < (1 << 16)) {
        return decodeThreeByteUtf8String(outBuf, val);                // RETURN
    }
    else if (val <= 0x10ffff) {
        return decodeFourByteUtf8String( outBuf, val);                // RETURN
    }
    else {
        LOOP_ASSERT(val, 0 && "value above 0x10ffff");
        return outBuf;                                                // RETURN
    }
}

bsl::string dumpVec(const bsl::vector<int>& vec)
    // Return a 'bsl::string' representation of the contents of 'vec' in
    // human-readable form.
{
    bsl::ostringstream oss;
    for (unsigned u = 0; u < vec.size(); ++u) {
        oss << (u ? " " : "") << vec[u];
    }
    return oss.str();
}

bsl::string dumpVec(const bsl::vector<unsigned int>& vec)
    // Return a 'bsl::string' representation of the contents of 'vec' in
    // human-readable form.
{
    const bsl::vector<int> *p = reinterpret_cast<const bsl::vector<int> *>(
                                                                         &vec);
    return dumpVec(*p);
}

bsl::string dumpVec(const bsl::vector<char>& vec)
    // Return a 'bsl::string' representation of the contents of 'vec' in
    // human-readable form.
{
    if (vec.empty()) {
        return "";                                                    // RETURN
    }

    bsl::string ret(&vec[0], vec.size());
    if ('\0' == vec[vec.size() - 1]) {
        ret.resize(ret.length() - 1);
    }

    return ret;
}

                                // -------
                                // CASE -1
                                // -------

namespace CASE_MINUS_1_NAMESPACE {

bsl::ostream& fourByteUtf8String(bsl::ostream& stream, unsigned val)
{
    unsigned bs[4];
    const char *hx = "\\x";

    ASSERT(0 == (val & ~((1 << 21) - 1)));
    ASSERT(0 != (val & ~((1 << 16) - 1)));

    bs[0] = ((val &  (7 << 18)) >> 18) | 0xf0;
    bs[1] = ((val & (63 << 12)) >> 12) | 0x80;
    bs[2] = ((val & (63 <<  6)) >>  6) | 0x80;
    bs[3] = ((val &  63       )      ) | 0x80;

    stream << bsl::hex << '"' << hx << bs[0] <<
                  hx << bs[1] << hx << bs[2] << hx << bs[3] << '"' << bsl::dec;

    return stream;
}

bsl::ostream& threeByteUtf8String(bsl::ostream& stream, unsigned val)
{
    unsigned bs[3];
    const char *hx = "\\x";

    ASSERT(0 == (val & ~((1 << 16) - 1)));
    ASSERT(0 != (val & ~((1 << 11) - 1)));

    bs[0] = ((val & (15 << 12)) >> 12) | 0xe0;
    bs[1] = ((val & (63 <<  6)) >>  6) | 0x80;
    bs[2] = ((val &  63       )      ) | 0x80;

    stream << bsl::hex << '"' << hx << bs[0] <<
                                 hx << bs[1] << hx << bs[2] << '"' << bsl::dec;

    return stream;
}

bsl::ostream& twoByteUtf8String(bsl::ostream& stream, unsigned val)
{
    unsigned bs[2];
    const char *hx = "\\x";

    ASSERT(0 == (val & ~((1 << 11) - 1)));
    ASSERT(0 != (val & ~((1 <<  7) - 1)));

    bs[0] = ((val & (31 <<  6)) >>  6) | 0xc0;
    bs[1] = ((val &  63       )      ) | 0x80;

    stream << bsl::hex << '"' << hx << bs[0] << hx << bs[1] <<'"' << bsl::dec;

    return stream;
}

bsl::ostream& oneByteUtf8String(bsl::ostream& stream, unsigned val)
{
    const char *hx = "\\x";

    ASSERT(0 == (val & ~((1 << 7) - 1)));
    ASSERT(0 !=  val);

    stream << '"';
    switch (val) {
      case '\n': {
        stream << "\\n";
      } break;
      case '\t': {
        stream << "\\t";
      } break;
      case '\\': {
        stream << "\\\\";
      } break;
      default: {
        if (bsl::isprint(val)) {
            stream << (char) val;
        }
        else {
            stream << bsl::hex << hx << val << bsl::dec;
        }
      }
    }
    stream << '"';

    return stream;
}

bsl::ostream& outputSequence(bsl::ostream& stream, unsigned val)
{
    if      (val < 0x80) {
        return oneByteUtf8String(  stream, val);                      // RETURN
    }
    else if (val < (1 << 11)) {
        return twoByteUtf8String(  stream, val);                      // RETURN
    }
    else if (val < (1 << 16)) {
        return threeByteUtf8String(stream, val);                      // RETURN
    }
    else if (val <= 0x10ffff) {
        return fourByteUtf8String( stream, val);                      // RETURN
    }
    else {
        LOOP_ASSERT(val, 0 && "value above 0x10ffff");
        return stream;                                                // RETURN
    }
}

}  // close namespace CASE_MINUS_1_NAMESPACE

bsl::string dumpUtf8Vec(const bsl::vector<char>& utf8Vec)
{
    bsl::ostringstream oss;

    oss << bsl::hex;
    oss << "UTF-8(";
    for (unsigned u = 0; u < utf8Vec.size(); ++u) {
        oss << (u > 0 ? ", " : "") << "0x" <<
                                         (unsigned) (unsigned char) utf8Vec[u];
    }
    oss << ')';

    return oss.str();
}

bsl::string dumpUtf32Vec(const bsl::vector<unsigned int>& utf32Vec)
{
    bsl::ostringstream oss;

    oss << bsl::hex;
    oss << "UTF-32(";
    for (unsigned u = 0; u < utf32Vec.size(); ++u) {
        oss << (u > 0 ? ", " : "") << "0x" << utf32Vec[u];
    }
    oss << ')';

    return oss.str();
}

int myRandSeed = 1234567890;
static inline
unsigned int myRand32()
{
    return ((unsigned int) bdlb::Random::generate15(&myRandSeed) << 20) ^
           ((unsigned int) bdlb::Random::generate15(&myRandSeed) <<  8) ^
           ((unsigned int) bdlb::Random::generate15(&myRandSeed) >>  4);
}

static inline
unsigned int myRand15()
{
    return (unsigned int) bdlb::Random::generate15(&myRandSeed);
}


static
unsigned int myRandUtf32Word()
{
    unsigned int typ = myRand15() & 15;

    if (typ < 2) {
        // ASCII

        unsigned int ret;
        do {
            ret = myRand15() & 0x7f;
        } while (! ret);

        return ret;                                                   // RETURN
    }
    else if (typ < 2 + 3) {
        // 2 octet

        unsigned int ret;
        do {
            ret = myRand15() & ((1 << 11) - 1);
        } while (ret < 0x80);

        return ret;                                                   // RETURN
    }
    else if (typ < 2 + 3 + 5) {
        // 3 octet -- legal or illegal

        unsigned int ret;
        do {
            ret = myRand32() & 0xffff;
        } while (ret < (1 << 11));

        return ret;                                                   // RETURN
    }
    else if (typ < 15) {
        // legal 4 octet

        unsigned int ret;
        ret = (myRand32() & 0xfffff) + 0x10000;
        ASSERT(ret <= 0x10ffff);
        ASSERT(ret >=  0x10000);

        return ret;                                                   // RETURN
    }
    else {
        // illegal 4 octet

        unsigned int ret;
        do {
            ret = myRand32();
        } while (ret <= 0x10ffff);

        return ret;                                                   // RETURN
    }
}

template <class TYPE>
struct NotEqual {
    // For passing to 'bsl::find_if'.

    // DATA
    TYPE d_word;

    // CREATOR
    explicit
    NotEqual(TYPE c) : d_word(c) {}

    // ACCESSORS
    bool operator()(TYPE c) const { return d_word != c; }
};

static const struct Utf32TableStruct {
    int           d_line;
    unsigned int  d_utf32Val;
    const char   *d_utf8String;
    const bool    d_error;
} utf32Table[] = {

    // minimal valid values encoded for 1-4 byte long UTF-8 sequences

    { L_, 1,             "\x01",              0 },
    { L_, 0x80,          "\xc2\x80",          0 },
    { L_, 1<<11,         "\xe0\xa0\x80",      0 },
    { L_, 1<<16,         "\xf0\x90\x80\x80",  0 },

    // medium, valid values encoded for 1-4 byte long UTF-8 sequences

    { L_, 'H',           "\x48",              0 },  // 1 byte
    { L_, 0x2f1,         "\xcb\xb1",          0 },  // 2 byte
    { L_, 0x2710,        "\xe2\x9c\x90",      0 },  // 3 byte
    { L_, 0xd7ff,        "\xed\x9f\xbf",      0 },  // 3 below UTF-16 bit plane
    { L_, 0xe000,        "\xee\x80\x80",      0 },  // 3 above UTF-16 bit plane
    { L_, 0x186a0,       "\xf0\x98\x9a\xa0",  0 },  // 4 byte

    // maximum valid values for 1-4 byte long UTF-8 sequences

    { L_, 0x7f,          "\x7f",              0 },  // 1 byte max
    { L_, (1<<11)-1,     "\xdf\xbf",          0 },  // 2 byte max
    { L_, (1<<16)-1,     "\xef\xbf\xbf",      0 },  // 3 byte max
    { L_, 0x10ffff,      "\xf4\x8f\xbf\xbf",  0 },  // 4 byte max

    // Values that are not valid Unicode because they are in the lower
    // UTF-16 bit plane.

    { L_, 0xd800,        "?",                 1 },
    { L_, 0xd8ff,        "?",                 1 },
    { L_, 0xd917,        "?",                 1 },
    { L_, 0xdaaf,        "?",                 1 },
    { L_, 0xdb09,        "?",                 1 },
    { L_, 0xdbff,        "?",                 1 },

    // Values that are not valid Unicode because they are in the upper
    // UTF-16 bit plane.

    { L_, 0xdc00,        "?",                 1 },
    { L_, 0xdcff,        "?",                 1 },
    { L_, 0xdd80,        "?",                 1 },
    { L_, 0xdea7,        "?",                 1 },
    { L_, 0xdf03,        "?",                 1 },
    { L_, 0xdfff,        "?",                 1 },

    // Values that are not valid Unicode because they are too high

    { L_, 0x110000,      "?",                 1 },
    { L_, 0x120000,      "?",                 1 },
    { L_, 1<<21,         "?",                 1 },
    { L_, 1<<29,         "?",                 1 },
    { L_, 0x10000000,    "?",                 1 },
    { L_, (0xffff0000),  "?",                 1 },
};
enum { NUM_UTF32_TABLE = sizeof utf32Table / sizeof *utf32Table };

static const struct Utf8TableStruct {
    int           d_line;
    const char   *d_utf8String;
    unsigned int  d_midVal;
    const bool    d_error;
    const int     d_truncBy;
} utf8Table[] = {

    // minimal UTF-8 values for 1-4 length octet sequences

    { L_, "1\x01z",              1,         0, 0 },
    { L_, "1\xc2\x80z",          0x80,      0, 0 },
    { L_, "1\xe0\xa0\x80z",      1<<11,     0, 0 },
    { L_, "1\xf0\x90\x80\x80z",  1<<16,     0, 0 },

    // medium valid values for various length UTF-8 octet sequences

    { L_, "1\x48z",              'H',       0, 0 },
    { L_, "1\xcb\xb1z",          0x2f1,     0, 0 },
    { L_, "1\xe2\x9c\x90z",      0x2710,    0, 0 },
    { L_, "1\xed\x9f\xbfz",      0xd7ff,    0, 0 },  // below UTF-16 bit plane
    { L_, "1\xee\x80\x80z",      0xe000,    0, 0 },  // above UTF-16 bit plane
    { L_, "1\xf0\x98\x9a\xa0z",  0x186a0,   0, 0 },  //

    // maximum valid values for various length UTF-8 octet sequences

    { L_, "1\x7fz",              0x7f,      0, 0 },
    { L_, "1\xdf\xbfz",          (1<<11)-1, 0, 0 },
    { L_, "1\xef\xbf\xbfz",      (1<<16)-1, 0, 0 },
    { L_, "1\xf4\x8f\xbf\xbfz",  0x10ffff,  0, 0 },

    // invalid UTF-8 encodings of zero of various lengths

    { L_, "1\xc0\x80z",          '?',       1, 0 },  // 2 byte zero
    { L_, "1\xe0\x80\x80z",      '?',       1, 0 },  // 3 byte zero
    { L_, "1\xf0\x80\x80\x80z",  '?',       1, 0 },  // 4 byte zero
    { L_, "1\xf8\x80\x80\x80\x80z", '?',    1, 0 },  // 5 byte zero

    // non-minimal UTF-8 encodings

    { L_, "1\xc1\xbfz",          '?',       1, 0 },  // 2 byte 1 too small
    { L_, "1\xe0\x9f\xbfz",      '?',       1, 0 },  // 3 byte 1 too small
    { L_, "1\xf0\x8f\xbf\xbfz",  '?',       1, 0 },  // 4 byte 1 too small

    // 4-byte encodings with invalid values too high

    { L_, "1\xf4\x90\x80\x80z",  '?',       1, 0 },  // 1 too much
    { L_, "1\xf7\xbf\xbf\xbfz",  '?',       1, 0 },  // WAY too much

    // 5 byte sequence (all 5 byte sequences are invalid UTF-8)

    { L_, "1\xfb\xbf\xbf\xbf\xbfz", '?',    1, 0 },

    // UTF-8 values that are invalid because their values are reserved for the
    // UTF-16 upper or lower bit planes

    { L_, "1\xed\xa0\x80z",      '?',       1, 0 },
    { L_, "1\xed\xa3\xbfz",      '?',       1, 0 },
    { L_, "1\xed\xb0\x80z",      '?',       1, 0 },
    { L_, "1\xed\xb3\xbfz",      '?',       1, 0 },
    { L_, "1\xed\xb6\x99z",      '?',       1, 0 },

    // incomplete UTF-8 sequences -- truncated early by a single byte value
    // (in all cases 'z') being unexpectedly encountered.

    { L_, "1\xc2z",              '?',       1, 1 },
    { L_, "1\xe0\xa0z",          '?',       1, 1 },
    { L_, "1\xe0z",              '?',       1, 2 },
    { L_, "1\xf0\x90\x80z",      '?',       1, 1 },
    { L_, "1\xf0\x90z",          '?',       1, 2 },
    { L_, "1\xf0z",              '?',       1, 3 },
    { L_, "1\xfb\xbf\xbf\xbfz",  '?',       1, 1 },
    { L_, "1\xfb\xbf\xbfz",      '?',       1, 2 },
    { L_, "1\xfb\xbfz",          '?',       1, 3 },
    { L_, "1\xfbz",              '?',       1, 4 },
};
enum { NUM_UTF8_TABLE = sizeof utf8Table / sizeof *utf8Table };

static const struct BetterUtf8TableStruct {
    int           d_line;
    const char   *d_utf8String;
    unsigned int  d_utf32Val;
    const bool    d_error;
    const int     d_truncBy;
} betterUtf8Table[] = {

    // minimal UTF-8 values for 1-4 length octet sequences

    { L_, "\x01",              1,         0, 0 },
    { L_, "\xc2\x80",          0x80,      0, 0 },
    { L_, "\xe0\xa0\x80",      1<<11,     0, 0 },
    { L_, "\xf0\x90\x80\x80",  1<<16,     0, 0 },

    // medium valid values for various length UTF-8 octet sequences

    { L_, "\x48",              'H',       0, 0 },
    { L_, "\xcb\xb1",          0x2f1,     0, 0 },
    { L_, "\xe2\x9c\x90",      0x2710,    0, 0 },
    { L_, "\xed\x9f\xbf",      0xd7ff,    0, 0 },  // below UTF-16 bit plane
    { L_, "\xee\x80\x80",      0xe000,    0, 0 },  // above UTF-16 bit plane
    { L_, "\xf0\x98\x9a\xa0",  0x186a0,   0, 0 },  //

    // maximum valid values for various length UTF-8 octet sequences

    { L_, "\x7f",              0x7f,      0, 0 },
    { L_, "\xdf\xbf",          (1<<11)-1, 0, 0 },
    { L_, "\xef\xbf\xbf",      (1<<16)-1, 0, 0 },
    { L_, "\xf4\x8f\xbf\xbf",  0x10ffff,  0, 0 },

    // invalid UTF-8 encodings of zero of various lengths

    { L_, "\xc0\x80",          '?',       1, 0 },  // 2 byte zero
    { L_, "\xe0\x80\x80",      '?',       1, 0 },  // 3 byte zero
    { L_, "\xf0\x80\x80\x80",  '?',       1, 0 },  // 4 byte zero
    { L_, "\xf8\x80\x80\x80\x80", '?',    1, 0 },  // 5 byte zero

    // non-minimal UTF-8 encodings

    { L_, "\xc1\xbf",          '?',       1, 0 },  // 2 byte 1 too small
    { L_, "\xe0\x9f\xbf",      '?',       1, 0 },  // 3 byte 1 too small
    { L_, "\xf0\x8f\xbf\xbf",  '?',       1, 0 },  // 4 byte 1 too small

    // 4-byte encodings with invalid values too high

    { L_, "\xf4\x90\x80\x80",  '?',       1, 0 },  // 1 too much
    { L_, "\xf7\xbf\xbf\xbf",  '?',       1, 0 },  // WAY too much

    // 5 byte sequence (all 5 byte sequences are invalid UTF-8)

    { L_, "\xfb\xbf\xbf\xbf\xbf", '?',    1, 0 },

    // UTF-8 values that are invalid because their values are reserved for the
    // UTF-16 upper or lower bit planes

    { L_, "\xed\xa0\x80",      '?',       1, 0 },
    { L_, "\xed\xa3\xbf",      '?',       1, 0 },
    { L_, "\xed\xb0\x80",      '?',       1, 0 },
    { L_, "\xed\xb3\xbf",      '?',       1, 0 },
    { L_, "\xed\xb6\x99",      '?',       1, 0 },

    // incomplete UTF-8 sequences -- truncated early by a single byte value
    // (in all cases 'z') being unexpectedly encountered.

    { L_, "\xc2",              '?',       1, 1 },
    { L_, "\xe0\xa0",          '?',       1, 1 },
    { L_, "\xe0",              '?',       1, 2 },
    { L_, "\xf0\x90\x80",      '?',       1, 1 },
    { L_, "\xf0\x90",          '?',       1, 2 },
    { L_, "\xf0",              '?',       1, 3 },
    { L_, "\xfb\xbf\xbf\xbf",  '?',       1, 1 },
    { L_, "\xfb\xbf\xbf",      '?',       1, 2 },
    { L_, "\xfb\xbf",          '?',       1, 3 },
    { L_, "\xfb",              '?',       1, 4 },
};
enum { NUM_BETTER_UTF8_TABLE      =
                              sizeof betterUtf8Table / sizeof *betterUtf8Table,
       BETTER_UTF8_TABLE_CONT_IDX = 4 };

int main(int argc, char **argv)
{
    int test = argc > 1 ? bsl::atoi(argv[1]) : 0;
    verbose = argc > 2;
    veryVerbose = argc > 3;
    veryVeryVerbose = argc > 4;
    veryVeryVeryVerbose = argc > 5;
    veryVeryVeryVeryVerbose = argc > 6;

    cout << "TEST " << __FILE__ << " CASE " << test << endl;

    // CONCERN: 'BSLS_REVIEW' failures should lead to test failures.
    bsls::ReviewFailureHandlerGuard reviewGuard(&bsls::Review::failByAbort);

    switch (test) { case 0:  // Zero is always the leading case.
      case 18: {
        // --------------------------------------------------------------------
        // USAGE EXAMPLE
        //   Simple example illustrating how one might use the 'utf8ToUtf32'
        //   and 'utf32ToUtf8' methods to translate between UTF-8 and UTF-32.
        //
        // Concerns:
        //   The usage example provided in the component header file must
        //   compile, link, and run on all platforms as shown.
        //
        // Plan:
        //   Start with some multilingual UTF-8, translate it to UTF-32 and
        //   then back again to UTF-8.
        //
        // Testing:
        //   Usage example.
        // --------------------------------------------------------------------

        if (verbose) cout << "USAGE EXAMPLE\n"
                             "=============\n";

// The following snippets of code illustrate a typical use of the
// 'bdlde::CharConvertUtf32' struct's utility functions, first converting from
// UTF-8 to UTF-32, and then converting back to make sure the round trip
// returns the same value.
//
// First, we declare a string of UTF-8 containing single-, double-, triple-,
// and quadruple-octet code points:
//..
    const char utf8MultiLang[] = {
        "Hello"                                         // -- ASCII
        "\xce\x97"         "\xce\x95"       "\xce\xbb"  // -- Greek
        "\xe4\xb8\xad"     "\xe5\x8d\x8e"               // -- Chinese
        "\xe0\xa4\xad"     "\xe0\xa4\xbe"               // -- Hindi
        "\xf2\x94\xb4\xa5" "\xf3\xb8\xac\x83" };        // -- Quad octets
//..
// Then, we declare an 'enum' summarizing the counts of code points in the
// string and verify that the counts add up to the length of the string:
//..
    enum { NUM_ASCII_CODE_POINTS   = 5,
           NUM_GREEK_CODE_POINTS   = 3,
           NUM_CHINESE_CODE_POINTS = 2,
           NUM_HINDI_CODE_POINTS   = 2,
           NUM_QUAD_CODE_POINTS    = 2 };
//
    ASSERT(1 * NUM_ASCII_CODE_POINTS +
           2 * NUM_GREEK_CODE_POINTS +
           3 * NUM_CHINESE_CODE_POINTS +
           3 * NUM_HINDI_CODE_POINTS +
           4 * NUM_QUAD_CODE_POINTS == bsl::strlen(utf8MultiLang));
//..
// Next, we declare the vector where our UTF-32 output will go, and a variable
// into which the number of code points written will be stored.  It is not
// necessary to create a 'utf32CodePointsWritten' variable, since the number of
// code points will be the size of the vector when we are done.
//..
    bsl::vector<unsigned int> v32;
//..
// Note that it is a waste of time to 'v32.reserve(sizeof(utf8MultiLang))'; it
// is entirely redundant -- 'v32' will automatically be grown to the correct
// size.  Also note that if 'v32' were not empty, that would not be a problem
// -- any contents will be discarded.
//
// Then, we do the translation to 'UTF-32':
//..
    int retVal = bdlde::CharConvertUtf32::utf8ToUtf32(&v32,
                                                      utf8MultiLang);
//
    ASSERT(0 == retVal);        // verify success
    ASSERT(0 == v32.back());    // verify null terminated
//..
// Next, we verify that the number of code points that was returned is correct.
// Note that in UTF-32, the number of Unicode code points written is the same
// as the number of 32-bit words written:
//..
    enum { EXPECTED_CODE_POINTS_WRITTEN =
                    NUM_ASCII_CODE_POINTS +
                    NUM_GREEK_CODE_POINTS +
                    NUM_CHINESE_CODE_POINTS +
                    NUM_HINDI_CODE_POINTS +
                    NUM_QUAD_CODE_POINTS  + 1 };
    ASSERT(EXPECTED_CODE_POINTS_WRITTEN == v32.size());
//..
// Next, we calculate and confirm the difference between the number of UTF-32
// words output and the number of bytes input.  The ASCII bytes will take 1
// 32-bit word apiece, the Greek code points are double octets that will become
// single 'unsigned int' values, the Chinese code points are encoded as UTF-8
// triple octets that will turn into single 32-bit words, the same for the
// Hindi code points, and the quad code points are quadruple octets that will
// turn into single 'unsigned int' words:
//..
    enum { SHRINKAGE =
                      NUM_ASCII_CODE_POINTS   * (1-1) +
                      NUM_GREEK_CODE_POINTS   * (2-1) +
                      NUM_CHINESE_CODE_POINTS * (3-1) +
                      NUM_HINDI_CODE_POINTS   * (3-1) +
                      NUM_QUAD_CODE_POINTS    * (4-1) };
//
    ASSERT(v32.size() == sizeof(utf8MultiLang) - SHRINKAGE);
//..
// Then, we go on to do the reverse 'utf32ToUtf8' transform to turn it back
// into UTF-8, and we should get a result identical to our original input.
// Declare a 'bsl::string' for our output, and a variable to count the number
// of code points translated:
//..
    bsl::string s;
    bsl::size_t codePointsWritten;
//..
// Again, note that it would be a waste of time for the caller to 'resize' or
// 'reserve' 'v32'; it will be automatically 'resize'd by the translator to the
// right length.
//
// Now, we do the reverse transform:
//..
    retVal = bdlde::CharConvertUtf32::utf32ToUtf8(&s,
                                                  v32.begin(),
                                                  &codePointsWritten);
//..
// Finally, we verify that a successful status was returned, that the output of
// the reverse transform was identical to the original input, and that the
// number of code points translated was as expected:
//..
    ASSERT(0 == retVal);
    ASSERT(utf8MultiLang  == s);
    ASSERT(s.length() + 1 == sizeof(utf8MultiLang));
//
    ASSERT(EXPECTED_CODE_POINTS_WRITTEN == codePointsWritten);
    ASSERT(v32.size()                   == codePointsWritten);
//..
      } break;
      case 17: {
        // --------------------------------------------------------------------
        // RANDOM TABLE DRIVEN UTF-8 -> UTF-32 TEST PLUS EMBEDDED NULLS
        //
        // Concerns:
        //: 1 That the translator can handle embedded nulls in UTF-8 input.
        //:   o This component and previous test cases were all written under
        //:     the assumption that 0 was invalid Unicode, to be used only as
        //:     as a terminating byte or word.  So it was necessary to write a
        //:     separate test case from scratch.
        //
        // Plan:
        //: 1 Iterate thousands of time, enough time to take about 0.1 sec on
        //:   Linux.
        //:   o Choose a length, in Unicode code points, of the UTF-8 input
        //:     string (not counting the embedded nulls)
        //:   o Choose 1 or 2 indexes where embedded '\0's will be embedded in
        //:     the input.
        //:   o Add randomly chosen UTF-8 sequences to the input string,
        //:     inserting embedded nulls at the appropriate places.  Make sure
        //:     no truncated code points are immediately followed by
        //:     continuation bytes.  Simultaneously build the expected UTF-32
        //:     output, and keep track of whether any error sequences have
        //:     occurred, thus anticipating the return value.
        //:   o Call the function to convert a UTF-8 string to a UTF-32 vector.
        //:   o Verify that the output is as expected, and also the return
        //:     code.
        // --------------------------------------------------------------------

        if (verbose) cout <<
            "\nRANDOM TABLE DRIVEN UTF-8 -> UTF-32 TEST PLUS EMBEDDED NULLS\n"
              "============================================================\n";

        // This test case is calibrated to run as many test cases as can be run
        // in 0.1 sec on Linux, which will be much faster than 30 sec on the
        // slowest architecture.

        bsls::Stopwatch sw;
        sw.start();

        bsl::string               utf8InStr;
        bsl::string               utf8ExpStr;
        bsl::string               utf8OutStr;
        bsl::size_t               utf8ExpNumBytesWritten;
        bsl::vector<unsigned int> utf32ExpVec;
        bsl::vector<unsigned int> utf32OutVec;
        bsl::vector<int>          idxVec;

        bsl::vector<char>         utf8OutVec;
        bsl::vector<char>         utf8ExpVec;

        enum { UNICODE_CODE_POINTS_MOD = 6 };

        for (int ti = 0; ti < 25 * 1000; ++ti) {
            const int  numCodePointsIn =
                                      myRand15() % UNICODE_CODE_POINTS_MOD + 1;
            const bool opposite        = ti & 1;
            unsigned int errorChar32 = 0x20 + myRand15() % (128-0x20);
            ASSERT(errorChar32 < 128);
            const char errorChar = static_cast<char>(errorChar32);
            const bdlde::ByteOrder::Enum endian = opposite
                                                ? oppositeEndian
                                                : bdlde::ByteOrder::e_HOST;

            utf8ExpNumBytesWritten = 0;

            // 'nullIdx0' and 'nullIdx1' are indexes where nulls are inserted.
            // If they have a value of '-1', no null is inserted.  We are only
            // interested in testing cases with at least 1 embedded null.

            int nullIdx0, nullIdx1;
            do {
                nullIdx0 = myRand15() % (numCodePointsIn + 2) - 1;
                nullIdx1 = myRand15() % (numCodePointsIn + 2) - 1;
            } while (-1 == nullIdx0 && -1 == nullIdx1);

            ASSERT(bsl::max(nullIdx0, nullIdx1) >  -1);
            ASSERT(bsl::max(nullIdx0, nullIdx1) <= numCodePointsIn);
            ASSERT(bsl::min(nullIdx0, nullIdx1) >= -1);

            bool prevTrunc = false;    // Was the prev char truncated?
            int expRc = 0;
            utf8InStr.clear();
            utf32ExpVec.clear();
            utf8ExpVec.clear();
            utf8ExpStr.clear();
            idxVec.clear();
            for (int tj = 0; true; ++tj) {
                if (nullIdx0 == tj) {
                    utf8InStr.  push_back('\0');
                    utf8ExpStr. push_back('\0');
                    utf32ExpVec.push_back(0);
                    idxVec.     push_back(-1);
                    prevTrunc = false;
                    ++utf8ExpNumBytesWritten;
                }
                if (nullIdx1 == tj) {
                    utf8InStr.  push_back('\0');
                    utf8ExpStr. push_back('\0');
                    utf32ExpVec.push_back(0);
                    idxVec.     push_back(-1);
                    prevTrunc = false;
                    ++utf8ExpNumBytesWritten;
                }

                if (tj == numCodePointsIn) {
                    break;
                }

                // Select the next char, making sure no continuation bytes
                // immediately follow truncated sequences (because that could
                // confuse our calculation of 'expRc').

                int tableIdx;
                do {
                    tableIdx = myRand15() % NUM_BETTER_UTF8_TABLE;
                } while (prevTrunc && tableIdx < BETTER_UTF8_TABLE_CONT_IDX);
                const BetterUtf8TableStruct& table = betterUtf8Table[tableIdx];

                if (table.d_error) {
                    utf8ExpStr .push_back(errorChar);
                    utf32ExpVec.push_back(opposite ? sb(errorChar32)
                                                   :    errorChar32);
                    ++utf8ExpNumBytesWritten;
                    expRc = bdlde::CharConvertStatus::k_INVALID_INPUT_BIT;
                }
                else {
                    utf8ExpStr += table.d_utf8String;
                    utf32ExpVec.push_back(opposite ? sb(table.d_utf32Val)
                                                   :    table.d_utf32Val);
                    utf8ExpNumBytesWritten += bsl::strlen(table.d_utf8String);
                }

                utf8InStr += table.d_utf8String;
                prevTrunc =  table.d_truncBy;

                idxVec.push_back(tableIdx);
            }
            utf32ExpVec.push_back(0);
            ++utf8ExpNumBytesWritten;

            int rc = Util::utf8ToUtf32(&utf32OutVec,
                                       utf8InStr,
                                       errorChar32,
                                       endian);
            ASSERT(expRc == rc);
            LOOP5_ASSERT(dumpVec(idxVec), utf32ExpVec.size(),
                utf32OutVec.size(), dumpVec(utf32ExpVec), dumpVec(utf32OutVec),
                                                   utf32ExpVec == utf32OutVec);
            ASSERT(!utf32OutVec.empty());

            bsl::size_t numCodePointsWritten = myRand15();
            rc = Util::utf32ToUtf8(&utf8OutStr,
                                   &utf32OutVec[0],
                                   utf32OutVec.size() - 1,
                                   &numCodePointsWritten,
                                   errorChar,
                                   endian);
            ASSERT(0 == rc);
            LOOP2_ASSERT(utf32OutVec.size(), numCodePointsWritten,
                                   utf32OutVec.size() == numCodePointsWritten);
            LOOP5_ASSERT(utf8OutStr, utf8InStr, expRc,
                                   utf8OutStr.length(), utf8ExpNumBytesWritten,
                            utf8OutStr.length() + 1 == utf8ExpNumBytesWritten);
            LOOP2_ASSERT(utf8ExpStr, utf8OutStr, utf8ExpStr == utf8OutStr);
            ASSERT(Utf8Util::isValid(&utf8OutStr[0], utf8OutStr.length()));

            numCodePointsWritten = myRand15();
            utf8ExpVec.clear();
            utf8ExpVec.insert(utf8ExpVec.begin(),
                              &utf8ExpStr[0],
                              &utf8ExpStr[0] + utf8ExpStr.length() + 1);

            rc = Util::utf32ToUtf8(&utf8OutVec,
                                   &utf32OutVec[0],
                                   utf32OutVec.size() - 1,
                                   &numCodePointsWritten,
                                   errorChar,
                                   endian);
            ASSERT(0 == rc);
            LOOP2_ASSERT(utf32OutVec.size(), numCodePointsWritten,
                                   utf32OutVec.size() == numCodePointsWritten);
            LOOP5_ASSERT(utf8OutStr, utf8InStr, expRc,
                                   utf8OutStr.length(), utf8ExpNumBytesWritten,
                                  utf8OutVec.size() == utf8ExpNumBytesWritten);
            LOOP3_ASSERT(errorChar, dumpVec(utf8ExpVec), dumpVec(utf8OutVec),
                                                     utf8ExpVec == utf8OutVec);

            for (bsl::size_t ii = utf8OutVec.size() + 1; 0 < ii--; ) {
                numCodePointsWritten = myRand15();
                bsl::size_t numBytesWritten = myRand15();
                const char initChar = '*';
                bsl::memset(&utf8OutVec[0], initChar, utf8OutVec.size());
                rc = Util::utf32ToUtf8(&utf8OutVec[0],
                                       ii,
                                       &utf32OutVec[0],
                                       utf32OutVec.size() - 1,
                                       &numCodePointsWritten,
                                       &numBytesWritten,
                                       errorChar,
                                       endian);
                ASSERT(rc == (ii == utf8OutVec.size()
                              ? 0
                              : Status::k_OUT_OF_SPACE_BIT));
                ASSERT(!!numCodePointsWritten == !!numBytesWritten);
                ASSERT(!!ii                   == !!numBytesWritten);
                ASSERT(numCodePointsWritten   <=   numBytesWritten);
                if (numCodePointsWritten) {
                    ASSERT('\0' == utf8OutVec[numBytesWritten - 1]);
                    ASSERT(0 == bsl::memcmp(&utf8OutVec[0],
                                            &utf8ExpVec[0],
                                            numBytesWritten - 1));
                }
                for (bsl::size_t jj = ii; jj < utf8OutVec.size(); ++jj) {
                    ASSERT(initChar == utf8OutVec[jj]);
                }
                ASSERT(Utf8Util::isValid(&utf8OutVec[0], numBytesWritten));
            }
        }
        sw.stop();

        if (verbose) P(sw.accumulatedWallTime());
      } break;
      case 16: {
        // --------------------------------------------------------------------
        // RANDOM UTF-8 -> UTF-32 TEST
        //
        // Concerns:
        //   That the translator can handle random input without dire effects.
        //: 1 The translator never segfaults and asserts never fail.
        //: 2 The output is always error-free UTF-32.  (Note we say
        //:   'error-free', not 'correct'.  Figuring out what the correct
        //:   UTF-32 would be given arbitrary UTF-8 input is about as hard as
        //:   writing this whole component, so the exact output is not
        //:   checked).  We merely check that it does not contain any invalid
        //:   UTF-32 values.
        //
        // Plan:
        //: 1 Iterate thousands of time, enough time to take about 0.1 sec on
        //:   Linux.
        //: 2 Generate 'numBytes', a length from 6-16, of bytes of input
        //:   that the test sequence is to be.
        //: 3 For each loop, iterate twice, once with a non-zero randomly
        //:   generated legal UTF-32 'errorWord', and once with
        //:   '0 == errorWord'.
        //: 4 Generate an input buffer 'utf8InBuf' of 'numBytes' bytes of
        //:   values that are purely random except that only the last one is 0.
        //: 5 Translate the UTF-8 to a UTF-32 vector 'utf32OutVec'.  Observe
        //:   that the 'out of space' bit of the return value is always 0.
        //: 6 Iterate 'len' from slightly more than 'utf32OutVec.size()' down
        //:   to 0, and for each value, translate 'utf8InBuf' to a buffer,
        //:   passing 'len' as capacity.
        //: 7 Observe that no more than 'len' words of output were written,
        //:   that there were no embedded 0's in the output, and that the final
        //:   word is 0.
        // --------------------------------------------------------------------

        if (verbose) cout << "\nPURELY RANDOM UTF-8 -> UTF-32 TEST\n"
                               "==================================\n";

        // This test case is calibrated to run as many test cases as can be run
        // in 0.1 sec on Linux, which will be much faster than 30 sec on the
        // slowest architecture.

        bsls::Stopwatch sw;
        sw.start();

        bsl::vector<char>         utf8OutVec;
        bsl::vector<unsigned int> utf32OutVec;

        enum { MAX_SEQ_LEN             = 17,
               SEQ_LEN_MOD             = MAX_SEQ_LEN - 1,
               MAX_UTF8_BYTES_INPUT    = MAX_SEQ_LEN };

        char utf8InBuf[          MAX_UTF8_BYTES_INPUT];
        unsigned int utf32OutBuf[MAX_UTF8_BYTES_INPUT + 1];
        enum { UTF32_OUT_BUF_LEN = sizeof(utf32OutBuf) / sizeof(int) };

        bsl::string utf8Seq;

        for (int ti = 0; ti < 25 * 1000; ++ti) {
            const unsigned numBytesIn   = myRand15() % SEQ_LEN_MOD + 2;
            const unsigned int fillWord = myRandUtf32Word();
            const bool opposite         = ti & 1;

            const bdlde::ByteOrder::Enum endian = opposite
                                                ? oppositeEndian
                                                : bdlde::ByteOrder::e_HOST;

            char *pc = utf8InBuf;
            for (unsigned tj = 1; tj < numBytesIn; ++tj) {
                char nextByte = static_cast<char>(myRand15() & 0xff);
                *pc++ = nextByte ? nextByte : 'a';
            }
            *pc++ = 0;
            ASSERT(pc - utf8InBuf <= MAX_UTF8_BYTES_INPUT);
            ASSERT(pc - utf8InBuf == (int) numBytesIn);
            ASSERT(bsl::strlen(utf8InBuf) + 1 == numBytesIn);

            bsl::vector<char> utf8InVec(utf8InBuf + 0, pc);

            for (int zeroErrorWord = 0; zeroErrorWord < 2; ++zeroErrorWord) {
                unsigned int errorWord;
                if (zeroErrorWord) {
                    errorWord = 0;
                }
                else {
                    int ret;
                    do {
                        errorWord = myRandUtf32Word();
                        unsigned int utf32ErrorSeq[] = { errorWord, 0 };

                        // Note UTF-32 -> UTF-8 translation is already
                        // well-tested.

                        bsl::string utf8ErrorSeq;
                        ret = Util::utf32ToUtf8(&utf8ErrorSeq,
                                                utf32ErrorSeq);
                    } while (0 != ret);
                    ASSERT(errorWord);
                }

                utf32OutVec.clear();
                utf32OutVec.resize(myRand15() % (2 * numBytesIn), fillWord);

                int ret = Util::utf8ToUtf32(&utf32OutVec,
                                            utf8InBuf,
                                            errorWord,
                                            endian);
                ASSERT(0 == (ret & ~Status::k_INVALID_INPUT_BIT));
                ASSERT(bsl::find(utf32OutVec.begin(), utf32OutVec.end(), 0) ==
                                                          &utf32OutVec.back());
                ASSERT(utf32OutVec.size() <= numBytesIn);

                bsl::size_t ncw = -1;
                ret = Util::utf32ToUtf8(&utf8OutVec,
                                        &utf32OutVec.front(),
                                        &ncw,
                                        '?',
                                        endian);
                ASSERT(0 == ret);    // this is important -- the UTF-32 output
                                     // must have no errors
                ASSERT(utf32OutVec.size() == ncw);
                ASSERT(bsl::find(utf8OutVec.begin(), utf8OutVec.end(), 0) ==
                                                           &utf8OutVec.back());
                LOOP3_ASSERT(errorWord, utf8OutVec.size(), numBytesIn,
                         errorWord >= 0x80 || utf8OutVec.size() <= numBytesIn);

                if (veryVeryVerbose) Q(Now do xlation to a UTF-8 buffer);

                for (bsl::size_t len = utf32OutVec.size() + 1; len >= 2;
                                                                       --len) {

                    if (veryVeryVeryVerbose) P(len);

                    bsl::fill(utf32OutBuf + 0,
                              utf32OutBuf + UTF32_OUT_BUF_LEN,
                              fillWord);

                    ncw = -1;
                    ret = Util::utf8ToUtf32(utf32OutBuf,
                                            len,
                                            utf8InBuf,
                                            &ncw,
                                            errorWord,
                                            endian);
                    LOOP6_ASSERT(ti, len, utf32OutVec.size(), ret,
                             dumpUtf8Vec(utf8InVec), dumpUtf32Vec(utf32OutVec),
                                              (len < utf32OutVec.size() + 1) ||
                                  0 == (ret & Status::k_OUT_OF_SPACE_BIT));
                    ASSERT(len > utf32OutVec.size() ? utf32OutVec.size() == ncw
                                                    : ncw == len);
                    ASSERT(bsl::find_if(utf32OutBuf + ncw,
                                        utf32OutBuf + UTF32_OUT_BUF_LEN,
                                        NotEqual<unsigned int>(fillWord)) ==
                                              utf32OutBuf + UTF32_OUT_BUF_LEN);
                    ASSERT(bsl::find(utf32OutBuf + 0,
                                     utf32OutBuf + ncw,
                                     0) == utf32OutBuf + ncw - 1);
                    ASSERT(0 == bsl::memcmp(utf32OutBuf,
                                            &utf32OutVec.front(),
                                            (ncw - 1) * sizeof(int)));
                    unsigned int *pos = bsl::find(utf32OutBuf + 0,
                                                  utf32OutBuf + ncw - 1,
                                                  opposite ? sb(errorWord)
                                                           :    errorWord);
                    LOOP8_ASSERT(ncw, pos - utf32OutBuf,
                           hx(errorWord), hx(sb(errorWord)),
                           (ret & Status::k_INVALID_INPUT_BIT), len,
                           dumpUtf32Vec(utf32OutVec), opposite,
                           0 == (ret & Status::k_INVALID_INPUT_BIT) ||
                           0 == errorWord ||
                           pos < utf32OutBuf + ncw - 1);
                }
            }
        }
        sw.stop();

        if (verbose) P(sw.accumulatedWallTime());
      } break;
      case 15: {
        // --------------------------------------------------------------------
        // TABLE-DRIVEN RANDOM UTF-8 -> UTF-32 SEQUENCES
        //
        // Concerns:
        //   That the translator performs well when passed a random assortment
        //   of UTF-8 sequences from 'utf8Table'.
        //: 1 No sequence causes segfaults and asserts never fail.
        //: 2 The translated output is exactly correct.
        //: 3 The return value is correct.
        //: 4 When the output is to a buffer that isn't long enough, it exactly
        //:   fills up the space in the buffer.
        //: 5 The UTF-32 output has *NO* errors in it.
        //
        // Plan:
        //: 1 Iterate thousands of time, enough time to take about 0.1 sec on
        //:   Linux.
        //: 2 Generate 'numCodePoints', a length from 2-7, of Unicode
        //:   code points that our test sequence is to be.
        //: 3 For each loop, iterate twice, once with a non-zero randomly
        //:   generated legal UTF-32 'errorWord', and once with
        //:   '0 == errorWord'.
        //: 4 When '0 != errorWord', generate a corresponding UTF-8 sequence
        //:   'errorSeq'.
        //: 5 Generate a sequence of bytes in buffer 'utf8InBuf' (and a copy in
        //:   vector 'utf8InVec') of 'numCodePoints' Unicode code points, but
        //:   randomly selecting UTF-8 sequences from 'utf8Table' (and
        //:   eliminating the preceding '1' and trailing 'z'.  Simultaneously
        //:   construct vector 'utf32ExpVec' of what we expect the UTF-32
        //:   output to be and vector 'utf8ExpVec' of what we expect the result
        //:   to be when that UTF-32 is translated back to UTF-8.
        //: 6 Translate 'utf8InBuf' to a UTF-32 vector 'utf32OutVec' and
        //:   observe the result and return value are as expected.
        //: 7 Translate 'utv32OutVec' to a UTF-8 vector 'utf8OutVec' and
        //:   observe the result and return value are as expected.
        //: 8 Iterate 'len' from slightly above the expected length of UTF-32
        //:   output down to 2, and translate 'utf8InBuf' to a UTF-32 buffer,
        //:   passing 'len' as capacity, and observe that the result and return
        //:   value are as expected.
        //: 9 Observe that no more than 'len' words of output were written,
        //:   that there were no embedded 0's in the output, and that the final
        //:   word is 0.
        // --------------------------------------------------------------------

        if (verbose) cout <<
                           "\nTABLE-DRIVEN RANDOM UTF-8 -> UTF-32 SEQUENCES\n"
                             "=============================================\n";

        // This test case is calibrated to run as many test cases as can be run
        // in 0.1 sec on Linux, which will be much faster than 30 sec on the
        // slowest architecture.

        bsls::Stopwatch sw;
        sw.start();

        bsl::vector<unsigned int> utf8InVec, utf32ExpVec;
        bsl::vector<char> utf8ExpVec;

        bsl::vector<char>         utf8OutVec;
        bsl::vector<unsigned int> utf32OutVec;

        enum { MAX_SEQ_LEN             = 7,
               SEQ_LEN_MOD             = MAX_SEQ_LEN - 1,
               MAX_UTF32_WORDS_WRITTEN = MAX_SEQ_LEN,
               MAX_UTF8_BYTES_INPUT    = (MAX_SEQ_LEN - 1) * 5 + 1,
               UTF8_TABLE_MOD          = NUM_UTF8_TABLE + 1 };

        char utf8InBuf[          MAX_UTF8_BYTES_INPUT];
        unsigned int utf32OutBuf[MAX_UTF32_WORDS_WRITTEN + 1];
        enum { UTF32_OUT_BUF_LEN = sizeof(utf32OutBuf) / sizeof(int) };

        bsl::string utf8Seq;

        for (int ti = 0; ti < 8 * 1000; ++ti) {
            const unsigned     numCodePointsIn = myRand15() % SEQ_LEN_MOD + 2;
            const unsigned int fillWord = myRandUtf32Word();
            const char fillByte = (char) (myRand15() % 0xff);
            const bool opposite = ti & 1;

            const bdlde::ByteOrder::Enum endian = opposite
                                                ? oppositeEndian
                                                : bdlde::ByteOrder::e_HOST;

            for (int zeroErrorWord = 0; zeroErrorWord < 2; ++zeroErrorWord) {
                unsigned int errorWord;
                bsl::string utf8ErrorSeq;
                if (zeroErrorWord) {
                    errorWord = 0;
                }
                else {
                    int ret;
                    do {
                        errorWord = myRandUtf32Word();
                        unsigned int utf32ErrorSeq[] = { errorWord, 0 };

                        // Note UTF-32 -> UTF-8 translation is already
                        // well-tested.

                        ret = Util::utf32ToUtf8(&utf8ErrorSeq,
                                                utf32ErrorSeq);
                    } while (0 != ret);
                    ASSERT(errorWord);
                    ASSERT(utf8ErrorSeq.length() >= 1);
                }

                utf8ExpVec. clear();
                utf32ExpVec.clear();

                char *pc = utf8InBuf;
                bool errorsPresent = false;
                bool prevTrunc = false;
                for (unsigned tj = 1; tj < numCodePointsIn; ++tj) {
                    unsigned idx;
                    bool repeat = true;
                    for (; repeat;) {
                        idx = myRand15() % UTF8_TABLE_MOD;

                        if (veryVeryVeryVerbose) P(idx);

                        if (NUM_UTF8_TABLE == idx) {
                            // continuation code point, unless previous was
                            // truncated

                            repeat = prevTrunc;
                            if (!prevTrunc) {
                                char cont = (char) (0x80|(myRand15() & 0x3f));
                                unsigned seqlen = myRand15() % 5 + 1;
                                bsl::memset(pc, cont, seqlen);
                                pc += seqlen;

                                errorsPresent = true;
                                prevTrunc = seqlen < 5;

                                if (errorWord) {
                                    utf8ExpVec.insert(utf8ExpVec.end(),
                                                      utf8ErrorSeq.begin(),
                                                      utf8ErrorSeq.end());
                                    utf32ExpVec.push_back(
                                         opposite ? sb(errorWord) : errorWord);
                                }
                            }
                        }
                        else {
                            const char *utf8Seq =
                                               utf8Table[idx].d_utf8String + 1;
                            bsl::size_t seqlen = bsl::strlen(utf8Seq) - 1;
                            ASSERT(seqlen <= 5);
                            ASSERT(seqlen >= 1);
                            bsl::memcpy(pc, utf8Seq, seqlen);
                            pc += seqlen;

                            repeat = false;
                            prevTrunc = utf8Table[idx].d_truncBy > 0;
                            if (utf8Table[idx].d_error) {
                                errorsPresent = true;

                                if (errorWord) {
                                    utf8ExpVec.insert(utf8ExpVec.end(),
                                                      utf8ErrorSeq.begin(),
                                                      utf8ErrorSeq.end());
                                    utf32ExpVec.push_back(
                                         opposite ? sb(errorWord) : errorWord);
                                }
                            }
                            else {
                                utf8ExpVec.insert(utf8ExpVec.end(),
                                                  utf8Seq,
                                                  utf8Seq + seqlen);
                                utf32ExpVec.push_back(
                                        opposite ? sb(utf8Table[idx].d_midVal)
                                                 :    utf8Table[idx].d_midVal);
                            }
                        }
                    }
                }
                *pc++ = 0;
                utf8ExpVec. push_back(0);
                utf32ExpVec.push_back(0);
                ASSERT(pc <= utf8InBuf + MAX_UTF8_BYTES_INPUT);
                LOOP4_ASSERT(ti, utf8ExpVec.size(), pc - utf8InBuf,
                                                errorWord, errorWord >= 0x80 ||
                                    (int) utf8ExpVec.size() <= pc - utf8InBuf);
                bsl::vector<char> utf8InVec(
                            utf8InBuf, utf8InBuf + bsl::strlen(utf8InBuf) + 1);

                utf32OutVec.clear();
                utf32OutVec.resize(myRand15() % (2 * numCodePointsIn),
                                                                     fillWord);

                int ret = Util::utf8ToUtf32(&utf32OutVec,
                                            utf8InBuf,
                                            errorWord,
                                            endian);
                ASSERT(ret == (errorsPresent ? Status::k_INVALID_INPUT_BIT
                                             : 0));
                LOOP3_ASSERT(ti, dumpUtf32Vec(utf32ExpVec),
                                                     dumpUtf32Vec(utf32OutVec),
                                                   utf32ExpVec == utf32OutVec);
                ASSERT(bsl::find(utf32OutVec.begin(), utf32OutVec.end(), 0) ==
                                                         &utf32OutVec.back());
                ASSERT((errorsPresent && !errorWord)
                                      ? utf32OutVec.size() <  numCodePointsIn
                                      : utf32OutVec.size() == numCodePointsIn);

                if (veryVeryVerbose) Q(Now do the return trip);

                utf8OutVec.clear();
                utf8OutVec.resize(myRand15() % (8 * numCodePointsIn),
                                                                     fillByte);

                bsl::size_t ncw = -1;
                ret = Util::utf32ToUtf8(&utf8OutVec,
                                        utf32OutVec.begin(),
                                        &ncw,
                                        '?',
                                        endian);
                ASSERT(0 == ret);    // this is important -- the UTF-32 output
                                     // must have no errors
                ASSERT(utf32ExpVec.size() == ncw);
                ASSERT(bsl::find(utf8OutVec.begin(), utf8OutVec.end(), 0) ==
                                                           &utf8OutVec.back());
                ASSERT(utf8ExpVec == utf8OutVec);

                if (veryVeryVerbose) Q(Now do xlation to a UTF-8 buffer);

                for (bsl::size_t len = utf32ExpVec.size() + 1; len >= 2;
                                                                       --len) {
                    bsl::fill(utf32OutBuf + 0,
                              utf32OutBuf + UTF32_OUT_BUF_LEN,
                              fillWord);

                    if (veryVeryVeryVerbose) P(len);

                    ncw = -1;
                    ret = Util::utf8ToUtf32(utf32OutBuf,
                                            len,
                                            utf8InBuf,
                                            &ncw,
                                            errorWord,
                                            endian);
                    LOOP6_ASSERT(ti, len, utf32ExpVec.size(), ret,
                             dumpUtf8Vec(utf8InVec), dumpUtf32Vec(utf32ExpVec),
                                 0 == (ret & Status::k_OUT_OF_SPACE_BIT) ||
                                               (len < utf32ExpVec.size() + 1));
                    ASSERT(errorsPresent || 0 ==
                                      (ret & Status::k_INVALID_INPUT_BIT));
                    ASSERT(len > utf32ExpVec.size() ? utf32ExpVec.size() == ncw
                                                    : ncw == len);
                    ASSERT(bsl::find_if(utf32OutBuf + ncw,
                                        utf32OutBuf + UTF32_OUT_BUF_LEN,
                                        NotEqual<unsigned int>(fillWord)) ==
                                              utf32OutBuf + UTF32_OUT_BUF_LEN);
                    ASSERT(bsl::find(utf32OutBuf + 0,
                                     utf32OutBuf + ncw,
                                     0) == utf32OutBuf + ncw - 1);
                    ASSERT(0 == bsl::memcmp(utf32OutBuf,
                                            &utf32ExpVec.front(),
                                            (ncw - 1) * sizeof(int)));
                }
            }
        }
        sw.stop();

        if (verbose) P(sw.accumulatedWallTime());
      } break;
      case 14: {
        // --------------------------------------------------------------------
        // RANDOM TEST UTF-32 -> UTF-8
        //
        // Concerns:
        //   That the UTF-32 -> UTF-8 translators will function properly with
        //  really randomly generated input.
        //: 1 That they produce correct output.
        //: 2 They return correct values.
        //: 3 When the output is to a buffer, they don't write past the end
        //:   of where they're supposed to.
        //: 4 The UTF-8 output should have *NO* errors in it.
        //
        // Plan:
        //: 1 Iterate thousands of times, enough to take 0.1 seconds on Linux.
        //: 2 For each iteration, generate a sequence of 1 to 6 UTF-32
        //:   code points (not counting the 0), using the function
        //:   'myRandUtf32Word', which has a possibility of generating any
        //:   non-zero 32 bit value, weighted toward the more interesting
        //:   values.
        //: 3 Iterate twice, once with a randomly generate ASCII 'errorByte'
        //:   and once where 'errorByte' is 0.
        //: 4 For the random sequence generated in '2', anticipate the
        //:   corresponding UTF-8 output, given the input and the value of
        //:   'errorByte'.  Also anticipate the UTF-32 that would result from
        //:   a reverse translation of that output.
        //: 5 Translate the UTF-32 to a UTF-8 'bsl::vector', verify it against
        //:   the anticipated results.
        //: 6 Translate the UTF-32 to a UTF-8 'bsl::string', verify it against
        //:   the anticipated results.
        //: 7 Translate the UTF-8 output that we created back to a UTF-32
        //:   vector, verify that the results are as anticipated.
        //: 8 Iterate 'len' from the length of the UTF-8 output plus one
        //:   down to 1, and repeatedly to UTF-32 -> UTF-8 translation with a
        //:   buffer destination, and capacity 'len', and observe that the
        //:   results are as they should be.
        // --------------------------------------------------------------------

        if (verbose) cout << "\nPURELY RANDOM TEST UTF-32 -> UTF-8\n"
                               "==================================\n";

        // This test case is calibrated to run as many test cases as can be run
        // in 0.1 sec on Linux, which will be much faster than 30 sec on the
        // slowest architecture.

        bsls::Stopwatch sw;
        sw.start();

        bsl::vector<unsigned int> utf32InVec, utf32ExpVec, origUtf32InVec;
        bsl::vector<char> utf8ExpVec;

        bsl::vector<char>         utf8OutVec;
        bsl::string               utf8OutStr;
        bsl::vector<unsigned int> utf32OutVec;

        enum { MAX_SEQ_LEN            = 7,
               SEQ_LEN_MOD            = MAX_SEQ_LEN - 2,
               MAX_UTF8_BYTES_WRITTEN = (MAX_SEQ_LEN - 1) * 4 + 1 };

        char utf8OutBuf[MAX_UTF8_BYTES_WRITTEN + 1];

        for (int ti = 0; ti < 5 * 1000; ++ti) {
            const unsigned numCodePointsIn = myRand15() % SEQ_LEN_MOD + 2;
            const char fillByte = (char) (myRand15() & 0xff);
            const bool opposite = ti & 1;

            const bdlde::ByteOrder::Enum endian = opposite
                                                ? oppositeEndian
                                                : bdlde::ByteOrder::e_HOST;

            origUtf32InVec. clear();
            for (unsigned tj = 1; tj < numCodePointsIn; ++tj) {
                origUtf32InVec.push_back(myRandUtf32Word());
            }
            origUtf32InVec.push_back(0);

            utf32InVec.clear();
            for (unsigned u = 0; u < origUtf32InVec.size(); ++u) {
                utf32InVec.push_back(opposite ? sb(origUtf32InVec[u])
                                              :    origUtf32InVec[u]);
            }

            for (int zeroErrorByte = 0; zeroErrorByte < 2; ++zeroErrorByte) {
                char errorByte = 0;
                if (!zeroErrorByte) {
                    errorByte = myRand15() % 0x80;
                    errorByte || (errorByte = '?');    // never zero
                }

                utf8ExpVec. clear();
                utf32ExpVec.clear();

                bool errorsPresent = false;
                unsigned int uc;
                for (unsigned int *pui = &origUtf32InVec.front(); (uc = *pui);
                                                                       ++pui) {
                    const bool IS_ERROR = (uc >= 0xd800 && uc <= 0xdfff) ||
                                                                 uc > 0x10ffff;

                    if (veryVeryVeryVerbose) {
                        P_(numCodePointsIn); P_((int) errorByte); P(IS_ERROR);
                    }

                    if (! IS_ERROR) {
                        char buffer[4];
                        char *pc = decodeUtf32(buffer, uc);
                        ASSERT(pc <= buffer + 4);

                        utf8ExpVec.insert(utf8ExpVec.end(), buffer, pc);
                        utf32ExpVec.push_back(opposite ? sb(uc) : uc);
                    }
                    else if (!zeroErrorByte) {
                        utf8ExpVec. push_back(errorByte);
                        utf32ExpVec.push_back(
                                        opposite ? sb((unsigned int) errorByte)
                                                 : errorByte);
                    }

                    errorsPresent |= IS_ERROR;
                }
                utf8ExpVec. push_back(0);
                utf32ExpVec.push_back(0);
                LOOP3_ASSERT(zeroErrorByte, utf32ExpVec.size(),
                                                               numCodePointsIn,
                       !zeroErrorByte ? utf32ExpVec.size() == numCodePointsIn
                                      : utf32ExpVec.size() <= numCodePointsIn);
                ASSERT(utf8ExpVec.size() <= MAX_UTF8_BYTES_WRITTEN);

                bsl::size_t ncw = -1;
                utf8OutVec.resize(myRand15() % 10);
                bsl::fill(utf8OutVec.begin(), utf8OutVec.end(), fillByte);
                int ret = Util::utf32ToUtf8(&utf8OutVec,
                                            &utf32InVec.front(),
                                            &ncw,
                                            errorByte,
                                            endian);
                ASSERT(ret == (errorsPresent ? Status::k_INVALID_INPUT_BIT
                                             : 0));
                ASSERT(ncw == utf32ExpVec.size());

                ASSERT(utf8OutVec.size() == utf8ExpVec.size());
                ASSERT(utf8OutVec        == utf8ExpVec);
                ASSERT(bsl::strlen(&utf8OutVec.front()) ==utf8OutVec.size()-1);

                utf8OutStr.resize(myRand15() % 10);
                bsl::fill(utf8OutStr.begin(), utf8OutStr.end(), fillByte);

                ncw = -1;
                ret = Util::utf32ToUtf8(&utf8OutStr,
                                        &utf32InVec.front(),
                                        &ncw,
                                        errorByte,
                                        endian);
                ASSERT(ret == (errorsPresent ? Status::k_INVALID_INPUT_BIT
                                             : 0));
                ASSERT(ncw == utf32ExpVec.size());
                ASSERT(! bsl::strcmp(utf8OutStr.c_str(), &utf8OutVec.front()));

                utf32OutVec.resize(myRand15() % 10);
                bsl::fill(utf32OutVec.begin(), utf32OutVec.end(), fillByte);

                ret = Util::utf8ToUtf32(&utf32OutVec,
                                        utf8ExpVec.begin(),
                                        zeroErrorByte ? 0 : '*',
                                        endian);
                ASSERT(0 == ret);
                ASSERT(utf32OutVec.size() == utf32ExpVec.size());
                ASSERT(utf32OutVec        == utf32ExpVec);

                for (bsl::size_t len = utf8ExpVec.size() + 1; len >= 1; --len){
                    bsl::fill(&utf8OutBuf[0], &utf8OutBuf[sizeof(utf8OutBuf)],
                                                                     fillByte);

                    if (veryVeryVeryVerbose) {
                        P_(numCodePointsIn); P_((int) errorByte); P(len);
                    }

                    ncw = -1;
                    bsl::size_t nbw = -1;
                    ret = Util::utf32ToUtf8(utf8OutBuf,
                                            len,
                                            &utf32InVec.front(),
                                            &ncw,
                                            &nbw,
                                            errorByte,
                                            endian);
                    if (!errorsPresent) {
                        ASSERT(0 == (ret & Status::k_INVALID_INPUT_BIT));
                    }
                    ASSERT((len < utf8ExpVec.size()) ==
                                     !!(ret & Status::k_OUT_OF_SPACE_BIT));
                    ASSERT(ncw <= utf8ExpVec.size());
                    ASSERT(ncw <= len);
                    ASSERT(nbw <= MAX_UTF8_BYTES_WRITTEN);
                    ASSERT(nbw <= len);
                    ASSERT(nbw >= (unsigned) bsl::max<IntPtr>(len - 4, 0));
                    ASSERT(utf8OutBuf + sizeof(utf8OutBuf) ==
                                  bsl::find_if(utf8OutBuf + nbw,
                                               utf8OutBuf + sizeof(utf8OutBuf),
                                               NotEqual<char>(fillByte)));
                    ASSERT(bsl::strlen(utf8OutBuf) + 1 == nbw);
                    ASSERT(! bsl::strncmp(utf8OutBuf,
                                          &utf8ExpVec.front(),
                                          nbw - 1));
                    ASSERT(0 == utf8OutBuf[nbw - 1]);
                }
            }
        }
        sw.stop();

        if (verbose) P(sw.accumulatedWallTime());
      } break;
      case 13: {
        // --------------------------------------------------------------------
        // RANDOM SEQUENCES TEST UTF-32 -> UTF-8 WITH ZERO ERRORCHAR
        //
        // Concerns:
        //   That the translators will function properly on randomly generated
        //   input.
        //
        // Plan:
        //   Use 'utf32Table' to generate random sequences of UTF-8 and
        //   anticipate the corresponding UTF-32, do the translation and
        //   verify the results.
        // --------------------------------------------------------------------

        if (verbose) cout <<
               "\nRANDOM SEQUENCES TEST UTF-32 -> UTF-8 WITH ZERO ERRORCHAR\n"
                 "=========================================================\n";

        // This test case is calibrated to run as many test cases as can be run
        // in 0.1 sec on Linux, which will be much faster than 30 sec on the
        // slowest architecture.

        bsls::Stopwatch sw;
        sw.start();

        bsl::vector<unsigned int> utf32InVec, utf32ExpVec;
        bsl::vector<char> utf8ExpVec;
        bsl::vector<char> bufferVec;

        for (int ti = 0; ti < 15 * 1000; ++ti) {
            const int numCodePointsIn = myRand32() % 4 + 1;
            const char fillByte = (char) (myRand15() & 0xff);
            const bool opposite = ti & 1;

            const bdlde::ByteOrder::Enum endian = opposite
                                                ? oppositeEndian
                                                : bdlde::ByteOrder::e_HOST;

            utf32InVec. clear();
            utf8ExpVec. clear();
            utf32ExpVec.clear();

            bool errorsPresent = false;
            for (int tj = 1; tj < numCodePointsIn; ++tj) {
                unsigned tr = myRand32() % NUM_UTF32_TABLE;
                unsigned int uc      = utf32Table[tr].d_utf32Val;
                const char *utf8Str  = utf32Table[tr].d_utf8String;
                const bool  IS_ERROR = utf32Table[tr].d_error;

                if (veryVeryVeryVerbose) { P_(numCodePointsIn); P(utf8Str); }

                utf32InVec.push_back(opposite ? sb(uc) : uc);
                if (! IS_ERROR) {
                    utf8ExpVec.insert(utf8ExpVec.end(),
                                      utf8Str,
                                      utf8Str + bsl::strlen(utf8Str));
                    utf32ExpVec.push_back(opposite ? sb(uc) : uc);
                }

                errorsPresent |= IS_ERROR;
            }
            utf32InVec. push_back(0);
            utf8ExpVec. push_back(0);
            utf32ExpVec.push_back(0);

            ASSERT((int) utf32InVec.size() == numCodePointsIn);
            bsl::size_t numCodePointsOut = utf32ExpVec.size();

            if (veryVerbose) Q(UTF-32 -> UTF-8);

            bsl::size_t ncw = -1;

            bsl::vector<char> utf8OutVec;
            int ret = Util::utf32ToUtf8(&utf8OutVec,
                                        &utf32InVec.front(),
                                        &ncw,
                                        0,
                                        endian);
            ASSERT(ret == (errorsPresent ? Status::k_INVALID_INPUT_BIT
                                         : 0));
            ASSERT(ncw == numCodePointsOut);

            ASSERT(utf8OutVec.size() == utf8ExpVec.size());
            ASSERT(utf8OutVec        == utf8ExpVec);

            if (veryVerbose) Q(UTF-8 -> UTF-32);

            bsl::vector<unsigned int> utf32OutVec;
            ret = Util::utf8ToUtf32(&utf32OutVec,
                                    &utf8OutVec.front(),
                                    0,
                                    endian);
            ASSERT(0 == ret);
            ASSERT(utf32OutVec.size() == numCodePointsOut);

            ASSERT(utf32ExpVec.size() == utf32OutVec.size());
            ASSERT(utf32ExpVec        == utf32OutVec);

            if (veryVerbose) Q(UTF-32 -> UTF-8 Buffer);

            for (IntPtr len = utf8OutVec.size() + 1; len >= 0; --len) {
                bufferVec.clear();
                bufferVec.resize(utf8OutVec.size() + 4, fillByte);

                const int expectedRet = len < (int) utf8OutVec.size() ?
                                            Status::k_OUT_OF_SPACE_BIT : 0;

                ncw = -1;
                bsl::size_t nbw = -1;
                ret = Util::utf32ToUtf8(&bufferVec.front(),
                                        (bsl::size_t) len,
                                        &utf32InVec.front(),
                                        &ncw,
                                        &nbw,
                                        0,
                                        endian);
                LOOP5_ASSERT(ti, len, utf8OutVec.size(), expectedRet, ret,
                        expectedRet == (ret & Status::k_OUT_OF_SPACE_BIT));
                ASSERT(ncw <= numCodePointsOut);
                ASSERT(len >= (int) utf8OutVec.size() ||
                                                      ncw <  numCodePointsOut);
                ASSERT(len <  (int) utf8OutVec.size() ||
                                                      ncw == numCodePointsOut);
                ASSERT(nbw <= utf8OutVec.size());
                ASSERT(len >= (int) utf8OutVec.size() ||
                                                     nbw <  utf8OutVec.size());
                ASSERT(len <  (int) utf8OutVec.size() ||
                                                     nbw == utf8OutVec.size());
                ASSERT(!nbw == !ncw);
                ASSERT(len > (int) utf8OutVec.size() || (int) nbw >= len - 4);
                ASSERT(!nbw || bsl::strlen(bufferVec.begin()) == nbw - 1);

                ASSERT(!nbw || 0 == bsl::strncmp(utf8OutVec.begin(),
                                                 bufferVec.begin(),
                                                 nbw - 1));
                ASSERT(bufferVec.end() == bsl::find_if(
                                                    &bufferVec[nbw],
                                                    bufferVec.end(),
                                                    NotEqual<char>(fillByte)));
            }
        }
        sw.stop();

        if (verbose) P(sw.accumulatedWallTime());
      } break;
      case 12: {
        // --------------------------------------------------------------------
        // RANDOM SEQUENCES TEST UTF-32 -> UTF-8
        //
        // Concerns:
        //   That the translators will function properly on randomly generated
        //   input.
        //
        // Plan:
        //   Use 'utf32Table' to generate random sequences of UTF-8 and
        //   anticipate the corresponding UTF-32, do the translation and
        //   verify the results.
        // --------------------------------------------------------------------

        if (verbose) cout << "\nRANDOM SEQUENCES TEST UTF-32 -> UTF-8\n"
                               "=====================================\n";

        // This test case is calibrated to run as many test cases as can be run
        // in 0.1 sec on Linux, which will be much faster than 30 sec on the
        // slowest architecture.

        bsls::Stopwatch sw;
        sw.start();

        bsl::vector<unsigned int> utf32InVec, utf32ExpVec;
        bsl::vector<char> utf8ExpVec;
        bsl::vector<char> bufferVec;

        for (int ti = 0; ti < 15 * 1000; ++ti) {
            const int numCodePoints = myRand32() % 6 + 2;
            const char fillByte = (char) (myRand15() & 0xff);
            const bool opposite = ti & 1;

            const bdlde::ByteOrder::Enum endian = opposite
                                                ? oppositeEndian
                                                : bdlde::ByteOrder::e_HOST;

            utf32InVec. clear();
            utf8ExpVec. clear();
            utf32ExpVec.clear();

            bool errorsPresent = false;
            for (int tj = 1; tj < numCodePoints; ++tj) {
                unsigned tr = myRand32() % NUM_UTF32_TABLE;
                unsigned int uc      = utf32Table[tr].d_utf32Val;
                const char *utf8Str  = utf32Table[tr].d_utf8String;
                const bool  IS_ERROR = utf32Table[tr].d_error;

                if (veryVeryVeryVerbose) { P_(numCodePoints); P(utf8Str); }

                utf32InVec.push_back(opposite ? sb(uc) : uc);
                utf8ExpVec.insert(utf8ExpVec.end(),
                                  utf8Str,
                                  utf8Str + bsl::strlen(utf8Str));
                unsigned int maybeErr = IS_ERROR ? '?' : uc;
                utf32ExpVec.push_back(opposite ? sb(maybeErr) : maybeErr);

                errorsPresent |= IS_ERROR;
            }
            utf32InVec. push_back(0);
            utf8ExpVec. push_back(0);
            utf32ExpVec.push_back(0);

            ASSERT((int) utf32InVec.size() == numCodePoints);

            if (veryVerbose) Q(UTF-32 -> UTF-8);

            bsl::size_t ncw = -1;

            bsl::vector<char> utf8OutVec;
            utf8OutVec.resize(myRand15() % 9, fillByte);
            int ret = Util::utf32ToUtf8(&utf8OutVec,
                                        &utf32InVec.front(),
                                        &ncw,
                                        '?',
                                        endian);
            ASSERT(ret == (errorsPresent ? Status::k_INVALID_INPUT_BIT
                                         : 0));
            ASSERT((int) ncw == numCodePoints);

            ASSERT(utf8OutVec.size() == utf8ExpVec.size());
            ASSERT(utf8OutVec        == utf8ExpVec);

            if (veryVerbose) Q(UTF-8 -> UTF-32);

            bsl::vector<unsigned int> utf32OutVec;
            utf32OutVec.resize(myRand15() % 9, myRand32());
            ret = Util::utf8ToUtf32(&utf32OutVec,
                                    &utf8OutVec.front(),
                                    '?',
                                    endian);
            ASSERT(0 == ret);
            ASSERT((int) utf32OutVec.size() == numCodePoints);

            ASSERT(utf32ExpVec.size() == utf32OutVec.size());
            ASSERT(utf32ExpVec        == utf32OutVec);

            if (veryVerbose) Q(UTF-32 -> UTF-8 Buffer);

            for (IntPtr len = utf8OutVec.size() + 1; len >= 2; --len) {
                bufferVec.clear();
                bufferVec.resize(utf8OutVec.size() + 4, fillByte);

                int expectedRet = len < (int) utf8OutVec.size() ?
                                            Status::k_OUT_OF_SPACE_BIT : 0;

                ncw = -1;
                bsl::size_t nbw = -1;
                ret = Util::utf32ToUtf8(&bufferVec.front(),
                                        (bsl::size_t) len,
                                        &utf32InVec.front(),
                                        &ncw,
                                        &nbw,
                                        '?',
                                        endian);
                LOOP5_ASSERT(ti, len, utf8OutVec.size(), expectedRet, ret,
                        expectedRet == (ret & Status::k_OUT_OF_SPACE_BIT));
                ASSERT((int) ncw <= numCodePoints);
                ASSERT(len >= (int) utf8OutVec.size() ||
                                                   (int) ncw <  numCodePoints);
                ASSERT(len <  (int) utf8OutVec.size() ||
                                                   (int) ncw == numCodePoints);
                ASSERT(nbw <= utf8OutVec.size());
                ASSERT(len >= (int) utf8OutVec.size() ||
                                                     nbw <  utf8OutVec.size());
                ASSERT(len <  (int) utf8OutVec.size() ||
                                                     nbw == utf8OutVec.size());
                ASSERT(len > (int) utf8OutVec.size() || (int) nbw >= len - 4);
                ASSERT(!nbw || bsl::strlen(bufferVec.begin()) == nbw - 1);

                ASSERT(!nbw || 0 == bsl::strncmp(utf8OutVec.begin(),
                                                 bufferVec.begin(),
                                                 nbw - 1));
                ASSERT(bufferVec.end() == bsl::find_if(
                                                    &bufferVec[nbw],
                                                    bufferVec.end(),
                                                    NotEqual<char>(fillByte)));
            }
        }
        sw.stop();

        if (verbose) P(sw.accumulatedWallTime());
      } break;
      case 11: {
        // --------------------------------------------------------------------
        // REAL PROSE TEST
        //
        // Concerns:
        //   That the translators will function properly on real,
        //   human-generated, multi-language prose.
        //
        // Plan:
        //: o The byte array 'utf8Multilang' above contains prose written in
        //:   Chinese, Hindi, French, and Greek written in UTF-8, with a few
        //:   4-octet sequences added.  This will be translated into UTF-32 and
        //:   back, which should be achievable without any errors, and the
        //:   final result should be identical to the original.
        // --------------------------------------------------------------------

        if (verbose) cout << "\nREAL PROSE TEST\n"
                               "===============\n";

        const bsl::size_t origLen = bsl::strlen(charUtf8MultiLang);
        ASSERT(origLen > 1000);

        if (verbose) P(origLen);

        bsl::vector<unsigned int> utf32Vec;
        int ret = Util::utf8ToUtf32(&utf32Vec, charUtf8MultiLang);
        ASSERT(0 == ret);

        ASSERT(utf32Vec.size() > 400);
        if (verbose) P(utf32Vec.size());

        const unsigned int fillWord = 0xffffff;

        bsl::vector<unsigned int> utf32VecBuffer;
        utf32VecBuffer.resize(utf32Vec.size() + 10, fillWord);
        bsl::size_t ncw = -1;
        ret = Util::utf8ToUtf32(&utf32VecBuffer.front(),
                                utf32Vec.size(),
                                charUtf8MultiLang,
                                &ncw);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);
        ASSERT(! bsl::memcmp(&utf32VecBuffer.front(),
                             &utf32Vec.front(),
                             sizeof(unsigned int) * ncw));
        ASSERT(utf32VecBuffer.end() == bsl::find_if(
                                            utf32VecBuffer.begin() + ncw,
                                            utf32VecBuffer.end(),
                                            NotEqual<unsigned int>(fillWord)));

        bsl::vector<unsigned int> utf32VecOpposite;
        ret = Util::utf8ToUtf32(&utf32VecOpposite,
                                charUtf8MultiLang,
                                '?',
                                oppositeEndian);
        ASSERT(0 == ret);
        ASSERT(utf32VecOpposite.size() == utf32Vec.size());
        ASSERT(utf32VecOpposite != utf32Vec);
        for (unsigned u = 0; u < utf32Vec.size(); ++u) {
            ASSERT(utf32Vec[u] == sb(utf32VecOpposite[u]));
        }

        bsl::vector<unsigned int> utf32VecOppositeBuffer;
        utf32VecOppositeBuffer.resize(utf32Vec.size() + 10, fillWord);
        ncw = -1;
        ret = Util::utf8ToUtf32(&utf32VecOppositeBuffer.front(),
                                utf32Vec.size(),
                                charUtf8MultiLang,
                                &ncw,
                                '?',
                                oppositeEndian);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);
        ASSERT(! bsl::memcmp(&utf32VecOppositeBuffer.front(),
                             &utf32VecOpposite.front(),
                             sizeof(unsigned int) * ncw));
        ASSERT(utf32VecBuffer.end() == bsl::find_if(
                                            utf32VecBuffer.begin() + ncw,
                                            utf32VecBuffer.end(),
                                            NotEqual<unsigned int>(fillWord)));

        ncw = -1;
        bsl::string utf8Str;
        ret = Util::utf32ToUtf8(&utf8Str, &utf32Vec.front(), &ncw);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);

        ASSERT(origLen == utf8Str.length());

        ASSERT(0 == bsl::strcmp(utf8Str.c_str(), charUtf8MultiLang));

        ncw = -1;
        bsl::string utf8StrB;
        ret = Util::utf32ToUtf8(&utf8StrB,
                                &utf32VecOpposite.front(),
                                &ncw,
                                '?',
                                oppositeEndian);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);
        ASSERT(utf8Str == utf8StrB);

        ncw = -1;
        bsl::vector<char> utf8Vec;
        ret = Util::utf32ToUtf8(&utf8Vec, &utf32Vec.front(), &ncw);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);

        ASSERT(origLen + 1 == utf8Vec.size());

        ASSERT(0 == bsl::strcmp(utf8Vec.begin(), charUtf8MultiLang));

        utf8Vec.clear();
        ret = Util::utf32ToUtf8(&utf8Vec,
                                &utf32VecOpposite.front(),
                                &ncw,
                                '?',
                                oppositeEndian);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);

        ASSERT(origLen + 1 == utf8Vec.size());

        ASSERT(0 == bsl::strcmp(utf8Vec.begin(), charUtf8MultiLang));

        const char fillByte = (char) 0xaf;

        bsl::vector<char> utf8VecBuffer;
        utf8VecBuffer.resize(utf8Vec.size() + 10, fillByte);
        ncw = -1;
        bsl::size_t nbw = -1;
        ret = Util::utf32ToUtf8(utf8VecBuffer.begin(),
                                utf8VecBuffer.size(),
                                &utf32Vec.front(),
                                &ncw,
                                &nbw);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);
        ASSERT(origLen + 1     == nbw);

        ASSERT(0 == bsl::strcmp(utf8VecBuffer.begin(), charUtf8MultiLang));
        ASSERT(utf8VecBuffer.end() == bsl::find_if(utf8VecBuffer.begin() + nbw,
                                                   utf8VecBuffer.end(),
                                                   NotEqual<char>(fillByte)));

        utf8VecBuffer.clear();
        utf8VecBuffer.resize(utf8Vec.size() + 10, fillByte);
        ncw = -1;
        nbw = -1;
        ret = Util::utf32ToUtf8(utf8VecBuffer.begin(),
                                utf8VecBuffer.size(),
                                &utf32VecOpposite.front(),
                                &ncw,
                                &nbw,
                                '?',
                                oppositeEndian);
        ASSERT(0 == ret);
        ASSERT(utf32Vec.size() == ncw);
        ASSERT(origLen + 1     == nbw);

        ASSERT(0 == bsl::strcmp(utf8VecBuffer.begin(), charUtf8MultiLang));
        ASSERT(utf8VecBuffer.end() == bsl::find_if(utf8VecBuffer.begin() + nbw,
                                                   utf8VecBuffer.end(),
                                                   NotEqual<char>(fillByte)));
      } break;
      case 10: {
        // --------------------------------------------------------------------
        // TESTING PRECONDITION TESTS
        //
        // Concerns:
        //   That the public functions in this component test their testable
        //   preconditions.
        //
        // Plan:
        //   Undefined behavior in this component is limited to
        //: 1 input strings not null terminated.
        //: 2 output buffer shorter than specified.
        //: 3 Illegal values of 'errorWord' or 'errorByte'.
        //: 4 Pointers to input and output streams are null
        //   of these, only '3' and '4' are testable by the methods, so we will
        //   test that these are caught by using 'bsls_asserttest'.  Follow up
        //   failing tests that write to containers with an assert to show that
        //   the containers still still have zero size, thus verifying that the
        //   tests were performed before any output was written.
        // --------------------------------------------------------------------

        if (verbose) cout << "\nTESTING PRECONDITION TESTS\n"
                               "==========================\n";

        bsls::AssertTestHandlerGuard guard;

        const unsigned int    utf32Input[] = { 0x100, 0x1000, 0 };
        const char            utf8Input [] = "woof";
        const PaddedStringRef utf8Sr(utf8Input);

        const unsigned int fillWord = 0xffffff;
        const char         fillByte = (char) 0xaf;

        const bsl::size_t minus1 = -1;

        (void)utf32Input;

        if (verbose) cout << "All illegal values of utf8 error byte\n";

        for (int i = 0x80; i < 0x100; ++i) {
            const char ERROR_CHAR = (char) i;

            if (veryVerbose) P(ERROR_CHAR);

            bsl::vector<char> utf8DestVec;
            bsl::string       utf8DestString;

            bsl::size_t ncw = minus1;
            ASSERT_FAIL(Util::utf32ToUtf8(&utf8DestVec,
                                          utf32Input,
                                          &ncw,
                                          ERROR_CHAR));
            ASSERT(minus1 == ncw);
            ASSERT(utf8DestVec.empty());

            ASSERT_FAIL(Util::utf32ToUtf8(&utf8DestString,
                                          utf32Input,
                                          &ncw,
                                          ERROR_CHAR));
            ASSERT(minus1 == ncw);
            ASSERT(utf8DestString.empty());

            utf8DestVec.resize(20, fillByte);
            bsl::size_t nbw = minus1;
            ASSERT_FAIL(Util::utf32ToUtf8(&utf8DestVec.front(),
                                          utf8DestVec.size(),
                                          utf32Input,
                                          &ncw,
                                          &nbw,
                                          ERROR_CHAR));
            ASSERT(minus1 == ncw);
            ASSERT(minus1 == nbw);
            ASSERT(fillByte == utf8DestVec.front());
        }

        if (verbose) cout << "UTF-8 <- UTF-32: null pointers";
        {
            bsl::vector<char> utf8DestVec;
            bsl::string       utf8DestString;

            ASSERT_FAIL(Util::utf32ToUtf8((bsl::vector<char> *) 0,
                                          utf32Input));
            ASSERT_FAIL(Util::utf32ToUtf8(&utf8DestVec,
                                          0));

            ASSERT_FAIL(Util::utf32ToUtf8((bsl::string *) 0,
                                          utf32Input));
            ASSERT_FAIL(Util::utf32ToUtf8(&utf8DestString,
                                          0));

            utf8DestVec.resize(10);
            ASSERT_FAIL(Util::utf32ToUtf8(&utf8DestVec.front(),
                                          utf8DestVec.size(),
                                          0));
            ASSERT_FAIL(Util::utf32ToUtf8((char *) 0,
                                          utf8DestVec.size(),
                                          utf32Input));
        }

        if (verbose) cout << "Some illegal values of utf32 error words\n";

        for (unsigned int errorWord = 0xd800; errorWord < 0xffffff;
                              errorWord = errorWord < 0xdfff
                                        ? errorWord + 1
                                        : 0xdfff == errorWord
                                        ? 0X10ffff + 1
                                        : errorWord + (errorWord - 0x10ffff)) {
            bsl::vector<unsigned int> utf32DestVec;
            ASSERT_FAIL(Util::utf8ToUtf32(&utf32DestVec,
                                          utf8Input,
                                          errorWord));
            ASSERT(utf32DestVec.empty());

            if (veryVeryVeryVerbose) P(errorWord);

            utf32DestVec.resize(10, fillWord);
            bsl::size_t ncw = minus1;
            ASSERT_FAIL(Util::utf8ToUtf32(&utf32DestVec.front(),
                                          utf32DestVec.size(),
                                          utf8Input,
                                          &ncw,
                                          errorWord));
            ASSERT(minus1 == ncw);
            ASSERT(fillWord == utf32DestVec.front());

            ASSERT_FAIL(Util::utf8ToUtf32(&utf32DestVec.front(),
                                          utf32DestVec.size(),
                                          utf8Sr,
                                          &ncw,
                                          errorWord));
            ASSERT(minus1 == ncw);
            ASSERT(fillWord == utf32DestVec.front());
        }

        if (verbose) cout << "UTF-32 <- UTF-8: null pointers\n";
        {
            typedef bsl::vector<unsigned int> Utf32Vec;

            Utf32Vec utf32DestVec;

            ASSERT_FAIL(Util::utf8ToUtf32((Utf32Vec *) 0,
                                          utf8Input));
            ASSERT_FAIL(Util::utf8ToUtf32(&utf32DestVec,
                                               0));
            utf32DestVec.resize(10);
            ASSERT_FAIL(Util::utf8ToUtf32(&utf32DestVec.front(),
                                          utf32DestVec.size(),
                                          0));
            ASSERT_FAIL(Util::utf8ToUtf32(&utf32DestVec.front(),
                                          utf32DestVec.size(),
                                          bslstl::StringRef()));
            ASSERT_FAIL(Util::utf8ToUtf32((unsigned int *) 0,
                                          utf32DestVec.size(),
                                          utf8Input));
        }
      } break;
      case 9: {
        // --------------------------------------------------------------------
        // TESTING UTF-32 -> UTF-8 WITH EXPLICIT 'errorByte'
        //
        // Concerns:
        //   That non-zero values other than '?' can be substituted for
        //   'errorByte'.
        //
        // Plan:
        //   Repeat the vector destination case from TC 7, substituting all
        //   ASCII values for 'errorByte' and observe the output.
        // --------------------------------------------------------------------

        if (verbose) cout <<
                    "TESTING UTF-32 -> UTF-8 WITH EXPLICIT 'errorByte'\n"
                    "======================================================\n";

        if (verbose) Q(Passing non-zero 'errorByte');

        for (int tm = 0; tm < 2 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { '1', UTF32_VAL, 'z', 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            for (int errChr = 1; errChr < 0x80; ++errChr) {

                if (veryVeryVerbose) { P_(ti); P_(UTF8_STRING); P(errChr); }

                bsl::vector<char> compareVec, outVec;
                compareVec.push_back('1');
                if (IS_ERROR) {
                    compareVec.push_back((char) errChr);
                }
                else {
                    for (const char *pc = UTF8_STRING; *pc; ++pc) {
                        compareVec.push_back(*pc);
                    }
                }
                compareVec.push_back('z');
                compareVec.push_back(0);

                bsl::size_t numCodePoints = -1;
                int ret = opposite
                        ? Util::utf32ToUtf8(&outVec,
                                            utf32Seq,
                                            &numCodePoints,
                                            (char) errChr,
                                            oppositeEndian)
                        : Util::utf32ToUtf8(&outVec,
                                            utf32Seq,
                                            &numCodePoints,
                                            (char) errChr);
                ASSERT(4 == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
                ASSERT(compareVec == outVec);
            }
        }

        if (verbose) Q(Explicitly Passing '0 == errorByte');

        for (int tm = 0; tm < 2 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { '1', UTF32_VAL, 'z', 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            bsl::vector<char> compareVec, outVec;
            compareVec.push_back('1');
            if (! IS_ERROR) {
                for (const char *pc = UTF8_STRING; *pc; ++pc) {
                    compareVec.push_back(*pc);
                }
            }
            compareVec.push_back('z');
            compareVec.push_back(0);

            bsl::size_t numCodePoints = -1;
            int ret = opposite
                    ? Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0);
            ASSERT((unsigned) 4 - IS_ERROR == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareVec == outVec);
        }
      } break;
      case 8: {
        // --------------------------------------------------------------------
        // Testing UTF-32 -> UTF-8 Translation With Zero error char
        //
        // Concerns:
        //: 1 That UTF-32 -> UTF-8 translation is performed correctly when
        //:   0 is passed to 'errorByte'.
        //:   o When the destination is a 'bsl::vector<char>'.
        //:   o When the destination is a 'bsl::string'
        //:   o When the destination is a buffer of limited length.
        //
        // Plan:
        //: 1 Repeat the tests from TC 7, omitting the 'check' iteration
        //:   and passing '0' to the 'errorByte' arguments.
        //: 2 For the buffer test, calculate 'enc', which is the expected
        //:   number of code points output in the buffer test, derived from the
        //:   previously calculated 'expectedNumCodePoints' from the vector and
        //:   string tests.
        // --------------------------------------------------------------------

        if (verbose) cout << "Testing UTF-32 -> UTF-8 Translation\n"
                             "===================================\n";

        if (verbose) Q(Testing Full Sequence);

        for (int tm = 0; tm < 2 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { '1', UTF32_VAL, 'z', 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }
            bsl::vector<char> compareVec, outVec;
            compareVec.push_back('1');
            if (!IS_ERROR) {
                for (const char *pc = UTF8_STRING; *pc; ++pc) {
                    compareVec.push_back(*pc);
                }
            }
            compareVec.push_back('z');
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            bsl::size_t expectedNumCodePoints = 4 - IS_ERROR;
            bsl::size_t numCodePoints = -1;
            int ret = opposite
                    ? Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareVec == outVec);

            bsl::string outStr;
            numCodePoints = -1;    ret = -1;

            ret = opposite
                ? Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0,
                                    oppositeEndian)
                : Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareStr == outStr);

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                if (veryVeryVerbose) { P_(ti); P_(UTF8_STRING); P(len); }

                expectedRet = IS_ERROR && len >= 2
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                               ? Status::k_OUT_OF_SPACE_BIT
                                               : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t enc =
                                       len >= cvs   ? expectedNumCodePoints
                                     : len == cvs-1 ? expectedNumCodePoints - 1
                                     : len >= 2     ? 2
                                     :                len;
                ASSERT(expectedNumCodePoints <= 4);
                const bsl::size_t expectedNumBytes =
                                   enc <= 2                    ? enc
                                 : enc == expectedNumCodePoints - 1 ? cvs - 1
                                 :                               cvs;

                bsl::size_t numBytes = -1;
                ret = opposite
                    ? Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0);
                LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                                 expectedNumBytes == numBytes);
                ASSERT(enc == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }

        if (verbose) Q(Testing Sequence Without Leading ASCII Val);

        for (int tm = 0; tm < 2 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { UTF32_VAL, 'z', 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }
            bsl::vector<char> compareVec, outVec;
            if (!IS_ERROR) {
                for (const char *pc = UTF8_STRING; *pc; ++pc) {
                    compareVec.push_back(*pc);
                }
            }
            compareVec.push_back('z');
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            bsl::size_t expectedNumCodePoints = 3 - IS_ERROR;
            bsl::size_t numCodePoints = -1;
            int ret = opposite
                    ? Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareVec == outVec);

            bsl::string outStr;
            numCodePoints = -1;    ret = -1;

            ret = opposite
                ? Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0,
                                    oppositeEndian)
                : Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareStr == outStr);

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                if (veryVeryVerbose) { P_(ti); P_(UTF8_STRING); P(len); }

                expectedRet = IS_ERROR && len >= 1
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                               ? Status::k_OUT_OF_SPACE_BIT
                                               : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t enc =
                                     len >= cvs     ? expectedNumCodePoints
                                   : len == cvs - 1 ? expectedNumCodePoints - 1
                                   :                  !!len;
                ASSERT(expectedNumCodePoints <= 3);
                const bsl::size_t expectedNumBytes =
                                     enc == expectedNumCodePoints     ? cvs
                                   : enc == expectedNumCodePoints - 1 ? cvs - 1
                                   :                                    !!enc;

                if (veryVeryVeryVerbose) {
                    P_(LINE);    P_(len);    P_(cvs);
                    P_(expectedNumCodePoints);  P_(enc);  P(expectedNumBytes);
                }

                bsl::size_t numBytes = -1;
                ret = opposite
                    ? Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0);
                LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                                 expectedNumBytes == numBytes);
                LOOP4_ASSERT(LINE, len, enc, numCodePoints,
                                                         enc == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }

        if (verbose) Q(Testing Sequence Without Trailing ASCII);

        for (int tm = 0; tm < 2 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { '1', UTF32_VAL, 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }
            bsl::vector<char> compareVec, outVec;
            compareVec.push_back('1');
            if (!IS_ERROR) {
                for (const char *pc = UTF8_STRING; *pc; ++pc) {
                    compareVec.push_back(*pc);
                }
            }
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            const bsl::size_t expectedNumCodePoints = 3 - IS_ERROR;
            bsl::size_t numCodePoints = -1;
            int ret = opposite
                    ? Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareVec == outVec);

            bsl::string outStr;
            numCodePoints = -1;    ret = -1;

            ret = opposite
                ? Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0,
                                    oppositeEndian)
                : Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareStr == outStr);

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                if (veryVeryVerbose) { P_(ti); P_(UTF8_STRING); P(len); }

                expectedRet = IS_ERROR && len >= 2
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                               ? Status::k_OUT_OF_SPACE_BIT
                                               : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t enc =
                                       len >= cvs   ? expectedNumCodePoints
                                     : len == cvs-1 ? expectedNumCodePoints - 1
                                     : len >= 2     ? 2
                                     :                len;
                ASSERT(expectedNumCodePoints <= 3);
                const bsl::size_t expectedNumBytes =
                                   enc <= 2                    ? enc
                                 : enc == expectedNumCodePoints - 1 ? cvs - 1
                                 :                               cvs;

                if (veryVeryVerbose) {
                    P_(LINE);    P_(len);    P_(cvs);
                    P_(expectedNumCodePoints);    P_(enc);
                    P(expectedNumBytes);
                }

                bsl::size_t numBytes = -1;
                ret = opposite
                    ? Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0);
                LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                                 expectedNumBytes == numBytes);
                ASSERT(enc == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }

        if (verbose) Q(Testing Sequence By Itself);

        for (int tm = 0; tm < 2 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { UTF32_VAL, 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }

            bsl::vector<char> compareVec, outVec;
            if (!IS_ERROR) {
                for (const char *pc = UTF8_STRING; *pc; ++pc) {
                    compareVec.push_back(*pc);
                }
            }
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            const bsl::size_t expectedNumCodePoints = 2 - IS_ERROR;
            bsl::size_t numCodePoints = -1;
            int ret = opposite
                    ? Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq,
                                        &numCodePoints,
                                        0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareVec == outVec);

            bsl::string outStr;
            numCodePoints = -1;    ret = -1;

            ret = opposite
                ? Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0,
                                    oppositeEndian)
                : Util::utf32ToUtf8(&outStr,
                                    utf32Seq,
                                    &numCodePoints,
                                    0);
            ASSERT(expectedNumCodePoints == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareStr == outStr);

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                expectedRet = IS_ERROR && len >= 1
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                               ? Status::k_OUT_OF_SPACE_BIT
                                               : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t enc = len >= cvs   ? expectedNumCodePoints
                                      :                !!len;
                ASSERT(expectedNumCodePoints <= 2);
                const bsl::size_t expectedNumBytes =
                                           enc <  expectedNumCodePoints ? !!enc
                                                                        :  cvs;

                if (veryVeryVerbose) {
                    P_(LINE);    P_(len);    P_(cvs);
                    P_(expectedNumCodePoints);
                    P_(enc);     P(expectedNumBytes);
                }

                bsl::size_t numBytes = -1;
                ret = opposite
                    ? Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0,
                                        oppositeEndian)
                    : Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq,
                                        &numCodePoints,
                                        &numBytes,
                                        0);
                LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                                 expectedNumBytes == numBytes);
                ASSERT(enc == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }
      } break;
      case 7: {
        // --------------------------------------------------------------------
        // Testing UTF-32 -> UTF-8 Translation
        //
        // Concerns:
        //: 1 That UTF-32 -> UTF-8 translation is performed correctly
        //:   o When the destination is a 'bsl::vector<char>'.
        //:   o When the destination is a 'bsl::string'
        //:   o When the destination is a buffer of limited length.
        //
        // Plan:
        //: 1 Test all the sequences in utf32Table
        //:   o When the destination is a 'bsl::vector<char>'.
        //:   o When the destination is a 'bsl::string'
        //:   o When the destination is a buffer of limited length.
        //: 2 Repeat the tests in 1
        //:   o Preceded, and followed, by an ASCII value
        //:   o Followed by an ASCII value
        //:   o Preceded by an ASCII value
        //:   o by itself
        //: 3 In all these tests, calculate and verify
        //:   o 'expectedRet', the expected return value of the call
        //:   o 'expectedNumCodePoints', the expected value to be returned by
        //:     the 'numCodePointsWritten' arg, if passed
        //:   o 'expectedNumBytes', the expected value to be returned by the
        //:     'numBytesWritten' arg, if passed
        //:   o 'compareVec' and 'compareStr' containing the anticipated
        //:     UTF-8 output sequence
        //: 4 Iterate to test
        //:   o check the number of code points returned (if returned)
        //:   o check the number of bytes returned (if returned)
        //:   o check running the test in opposite to host byte order
        //: 5 When calling the buffer output routine, iterate the variable
        //:   'len' to be passed to the 'capacity' arg, from more than enough
        //:   down to zero and observe that the translator translates as much
        //:   of the sequence as will fit.
        // --------------------------------------------------------------------

        if (verbose) cout << "Testing UTF-32 -> UTF-8 Translation\n"
                             "===================================\n";

        if (verbose) Q(Testing Full Sequence);

        for (int tm = 0; tm < 8 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;
            const bool          checkNumCPs = (tm/NUM_UTF32_TABLE) & 2;
            const bool          checkNBytes = (tm/NUM_UTF32_TABLE) & 4;

            if (!checkNumCPs && (checkNBytes || opposite)) {
                continue;
            }

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { '1', UTF32_VAL, 'z', 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }

            bsl::vector<char> compareVec, outVec;
            compareVec.push_back('1');
            for (const char *pc = UTF8_STRING; *pc; ++pc) {
                compareVec.push_back(*pc);
            }
            compareVec.push_back('z');
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR ? Status::k_INVALID_INPUT_BIT : 0;

            bsl::size_t numCodePoints = -1;
            int ret;

            if (!checkNBytes) {
                ret = checkNumCPs
                    ? opposite
                      ? Util::utf32ToUtf8(&outVec,
                                          utf32Seq,
                                          &numCodePoints,
                                          '?',
                                          oppositeEndian)
                      : Util::utf32ToUtf8(&outVec,
                                          utf32Seq,
                                          &numCodePoints)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq);

                ASSERT(!checkNumCPs || 4 == numCodePoints);

                LOOP5_ASSERT(LINE, checkNumCPs, opposite, expectedRet, ret,
                                                           expectedRet == ret);
                LOOP3_ASSERT(LINE, checkNumCPs, opposite,
                                                         compareVec == outVec);

                bsl::string outStr;
                numCodePoints = -1;    ret = -1;

                ret = checkNumCPs
                    ? opposite
                      ? Util::utf32ToUtf8(&outStr,
                                          utf32Seq,
                                          &numCodePoints,
                                          '?',
                                          oppositeEndian)
                      : Util::utf32ToUtf8(&outStr,
                                          utf32Seq,
                                          &numCodePoints)
                    : Util::utf32ToUtf8(&outStr,
                                        utf32Seq);

                ASSERT(!checkNumCPs || 4 == numCodePoints);

                LOOP5_ASSERT(LINE, checkNumCPs, opposite, expectedRet, ret,
                                                           expectedRet == ret);
                LOOP3_ASSERT(LINE, checkNumCPs, opposite,compareStr == outStr);
            }

            if (!checkNBytes && opposite) {
                continue;
            }

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                expectedRet = IS_ERROR && len >= 2
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                               ? Status::k_OUT_OF_SPACE_BIT
                                               : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t expectedNumCodePoints = len >= cvs   ? 4
                                                   : len == cvs-1 ? 3
                                                   : len >= 2     ? 2
                                                   :                len;
                ASSERT(expectedNumCodePoints <= 4);
                const bsl::size_t expectedNumBytes =
                            expectedNumCodePoints <= 2 ? expectedNumCodePoints
                          : expectedNumCodePoints == 3 ? cvs - 1
                          :                              cvs;

                bsl::size_t numBytes = -1;

                ret = checkNumCPs
                    ? checkNBytes
                      ? opposite
                        ? Util::utf32ToUtf8(outBuf,
                                            len,
                                            utf32Seq,
                                            &numCodePoints,
                                            &numBytes,
                                            '?',
                                            oppositeEndian)
                        : Util::utf32ToUtf8(outBuf,
                                            len,
                                            utf32Seq,
                                            &numCodePoints,
                                            &numBytes)
                      : Util::utf32ToUtf8(outBuf,
                                          len,
                                          utf32Seq,
                                          &numCodePoints)
                    : Util::utf32ToUtf8(outBuf,
                                        len,
                                        utf32Seq);

                ASSERT(!checkNumCPs || expectedNumCodePoints == numCodePoints);
                LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                 !checkNBytes || expectedNumBytes == numBytes);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }

        if (verbose) Q(Testing Sequence Without Leading ASCII Val);

        for (int tm = 0; tm < 8 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;
            const bool          checkNumCPs = (tm/NUM_UTF32_TABLE) & 2;
            const bool          checkNBytes = (tm/NUM_UTF32_TABLE) & 4;

            if (!checkNumCPs && (checkNBytes || opposite)) {
                continue;
            }

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { UTF32_VAL, 'z', 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }
            bsl::vector<char> compareVec, outVec;
            for (const char *pc = UTF8_STRING; *pc; ++pc) {
                compareVec.push_back(*pc);
            }
            compareVec.push_back('z');
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            bsl::size_t numCodePoints = -1;
            int ret;

            ret = checkNumCPs
                ? opposite
                  ? Util::utf32ToUtf8(&outVec,
                                      utf32Seq,
                                      &numCodePoints,
                                      '?',
                                      oppositeEndian)
                  : Util::utf32ToUtf8(&outVec,
                                      utf32Seq,
                                      &numCodePoints)
                : Util::utf32ToUtf8(&outVec,
                                    utf32Seq);

            ASSERT(!checkNumCPs || 3 == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareVec == outVec);

            bsl::string outStr;
            numCodePoints = -1;    ret = -1;

            ret = checkNumCPs
                ? opposite
                  ? Util::utf32ToUtf8(&outStr,
                                      utf32Seq,
                                      &numCodePoints,
                                      '?',
                                      oppositeEndian)
                  : Util::utf32ToUtf8(&outStr,
                                      utf32Seq,
                                      &numCodePoints)
                : Util::utf32ToUtf8(&outStr,
                                    utf32Seq);

            ASSERT(!checkNumCPs || 3 == numCodePoints);

            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(compareStr == outStr);

            if (!checkNBytes && opposite) {
                continue;
            }

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                expectedRet = IS_ERROR && len >= 1
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                          ? Status::k_OUT_OF_SPACE_BIT : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t expectedNumCodePoints = len >= cvs   ? 3
                                                   : len == cvs-1 ? 2
                                                   : len >= 1     ? 1
                                                   :                0;
                ASSERT(expectedNumCodePoints <= 3);
                const bsl::size_t expectedNumBytes =
                            expectedNumCodePoints <= 1 ? expectedNumCodePoints
                          : expectedNumCodePoints == 2 ? cvs - 1
                          :                              cvs;

                bsl::size_t numBytes = -1;
                ret = -1;

                ret = checkNBytes
                    ? opposite
                      ? Util::utf32ToUtf8(outBuf,
                                          len,
                                          utf32Seq,
                                          &numCodePoints,
                                          &numBytes,
                                          '?',
                                          oppositeEndian)
                      : Util::utf32ToUtf8(outBuf,
                                          len,
                                          utf32Seq,
                                          &numCodePoints,
                                          &numBytes)
                    : checkNumCPs
                      ? Util::utf32ToUtf8(outBuf,
                                          len,
                                          utf32Seq,
                                          &numCodePoints)
                      : Util::utf32ToUtf8(outBuf,
                                          len,
                                          utf32Seq);

                ASSERT(!checkNumCPs || expectedNumCodePoints == numCodePoints);
                ASSERT(!checkNBytes || expectedNumBytes == numBytes);
                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                       0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }

        if (verbose) Q(Testing Sequence Without Trailing ASCII);

        for (int tm = 0; tm < 8 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;
            const bool          checkNumCPs = (tm/NUM_UTF32_TABLE) & 2;
            const bool          checkNBytes = (tm/NUM_UTF32_TABLE) & 4;

            if (!checkNumCPs && (checkNBytes || opposite)) {
                continue;
            }

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { '1', UTF32_VAL, 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }

            bsl::vector<char> compareVec, outVec;
            compareVec.push_back('1');
            for (const char *pc = UTF8_STRING; *pc; ++pc) {
                compareVec.push_back(*pc);
            }
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            int expectedRet = IS_ERROR
                            ? Status::k_INVALID_INPUT_BIT
                            : 0;

            bsl::size_t numCodePoints = -1;
            int ret;

            if (!checkNBytes) {
                ret = checkNumCPs
                    ? opposite
                      ? Util::utf32ToUtf8(&outVec,
                                          utf32Seq,
                                          &numCodePoints,
                                          '?',
                                          oppositeEndian)
                      : Util::utf32ToUtf8(&outVec,
                                          utf32Seq,
                                          &numCodePoints)
                    : Util::utf32ToUtf8(&outVec,
                                        utf32Seq);
                ASSERT(!checkNumCPs || 3 == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
                ASSERT(compareVec == outVec);

                bsl::string outStr;
                numCodePoints = -1;    ret = -1;

                ret = checkNumCPs
                    ? opposite
                      ? Util::utf32ToUtf8(&outStr,
                                          utf32Seq,
                                          &numCodePoints,
                                          '?',
                                          oppositeEndian)
                      : Util::utf32ToUtf8(&outStr,
                                          utf32Seq,
                                          &numCodePoints)
                    : Util::utf32ToUtf8(&outStr,
                                        utf32Seq);
                ASSERT(!checkNumCPs || 3 == numCodePoints);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
                ASSERT(compareStr == outStr);
            }

            if (!checkNBytes && opposite) {
                continue;
            }

            for (bsl::size_t len = compareVec.size() + 2;
                                          (bsl::size_t) -1 != len; --len) {
                char outBuf[100];
                bsl::memset(outBuf, -1, sizeof(outBuf));
                numCodePoints = -1;

                expectedRet = IS_ERROR && len >= 2
                                     ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < compareVec.size()
                                           ? Status::k_OUT_OF_SPACE_BIT
                                           : 0;

                const bsl::size_t cvs = compareVec.size();
                const bsl::size_t expectedNumCodePoints = len >= cvs ? 3
                                                   : len >= 2   ? 2
                                                   :              len;
                ASSERT(expectedNumCodePoints <= 4);
                const bsl::size_t expectedNumBytes =
                            expectedNumCodePoints <= 2 ? expectedNumCodePoints
                          :                              cvs;

                bsl::size_t numBytes = -1;
                ret = checkNumCPs
                    ? checkNBytes
                      ? opposite
                        ? Util::utf32ToUtf8(outBuf,
                                            len,
                                            utf32Seq,
                                            &numCodePoints,
                                            &numBytes,
                                            '?',
                                            oppositeEndian)
                        : Util::utf32ToUtf8(outBuf,
                                            len,
                                            utf32Seq,
                                            &numCodePoints,
                                            &numBytes)
                      : Util::utf32ToUtf8(outBuf,
                                            len,
                                            utf32Seq,
                                            &numCodePoints)
                    : Util::utf32ToUtf8(outBuf,
                                          len,
                                          utf32Seq);

                ASSERT(!checkNumCPs || expectedNumCodePoints == numCodePoints);
                LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                 !checkNBytes || expectedNumBytes == numBytes);

                LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
            }
        }

        if (verbose) Q(Testing Sequence Without Leading or Trailing ASCII Val);

        for (int tm = 0; tm < 8 * NUM_UTF32_TABLE; ++tm) {
            const int           ti          = tm % NUM_UTF32_TABLE;
            const bool          opposite    = (tm/NUM_UTF32_TABLE) & 1;
            const bool          checkNumCPs = (tm/NUM_UTF32_TABLE) & 2;
            const bool          checkNBytes = (tm/NUM_UTF32_TABLE) & 4;

            if (!checkNumCPs && (checkNBytes || opposite)) {
                continue;
            }

            const int           LINE        = utf32Table[ti].d_line;
            const unsigned int  UTF32_VAL   = utf32Table[ti].d_utf32Val;
            const char         *UTF8_STRING = utf32Table[ti].d_utf8String;
            const bool          IS_ERROR    = utf32Table[ti].d_error;

            unsigned int utf32Seq[] = { UTF32_VAL, 0 };
            enum { UTF32_SEQ_LEN = sizeof utf32Seq / sizeof *utf32Seq };
            if (opposite) {
                for (int tj = 0; tj < UTF32_SEQ_LEN; ++tj) {
                    utf32Seq[tj] = sb(utf32Seq[tj]);
                }
            }

            bsl::vector<char> compareVec, outVec;
            for (const char *pc = UTF8_STRING; *pc; ++pc) {
                compareVec.push_back(*pc);
            }
            compareVec.push_back(0);
            const bsl::string compareStr = &compareVec[0];

            for (int check = 0; check < 2; ++check) {
                //..
                // check == 0, check 'numCodePoints' && 'numBytes'
                // check == 1: check 'numCodePoints'
                // check == 2: check neither
                //..

                int expectedRet = IS_ERROR
                                ? Status::k_INVALID_INPUT_BIT
                                : 0;

                if (veryVeryVerbose) { P_(ti); P_(UTF8_STRING); P(check); }

                bsl::size_t numCodePoints = -1;
                int ret;

                if (!checkNBytes) {
                    ret = checkNumCPs
                        ? opposite
                          ? Util::utf32ToUtf8(&outVec,
                                              utf32Seq,
                                              &numCodePoints,
                                              '?',
                                              oppositeEndian)
                          : Util::utf32ToUtf8(&outVec,
                                              utf32Seq,
                                              &numCodePoints)
                        : Util::utf32ToUtf8(&outVec,
                                            utf32Seq);

                    ASSERT(!checkNumCPs || 2 == numCodePoints);

                    LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
                    ASSERT(compareVec == outVec);

                    bsl::string outStr;
                    numCodePoints = -1;    ret = -1;

                    ret = checkNumCPs
                        ? opposite
                          ? Util::utf32ToUtf8(&outStr,
                                              utf32Seq,
                                              &numCodePoints,
                                              '?',
                                              oppositeEndian)
                          : Util::utf32ToUtf8(&outStr,
                                              utf32Seq,
                                              &numCodePoints)
                        : Util::utf32ToUtf8(&outStr,
                                            utf32Seq);

                    ASSERT(!checkNumCPs || 2 == numCodePoints);

                    LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
                    ASSERT(compareStr == outStr);
                }

                if (!checkNBytes && opposite) {
                    continue;
                }

                for (bsl::size_t len = compareVec.size() + 2;
                                              (bsl::size_t) -1 != len; --len) {
                    char outBuf[100];
                    bsl::memset(outBuf, -1, sizeof(outBuf));
                    numCodePoints = -1;

                    expectedRet = IS_ERROR && len >= 1
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                    expectedRet |= len < compareVec.size()
                                               ? Status::k_OUT_OF_SPACE_BIT
                                               : 0;

                    const bsl::size_t cvs = compareVec.size();
                    const bsl::size_t expectedNumCodePoints = len >= cvs   ? 2
                                                       : len >= 1     ? 1
                                                       :                0;
                    ASSERT(expectedNumCodePoints <= 3);
                    const bsl::size_t expectedNumBytes =
                            expectedNumCodePoints == 2 ? cvs
                                                       : expectedNumCodePoints;

                    if (veryVeryVerbose) {
                        P_(LINE);  P_(tm/NUM_UTF32_TABLE);   P_(len);  P_(cvs);
                        P_(expectedNumCodePoints);       P(expectedNumBytes);
                    }

                    bsl::size_t numBytes = -1;
                    ret = checkNumCPs
                        ? checkNBytes
                          ? opposite
                            ? Util::utf32ToUtf8(outBuf,
                                                len,
                                                utf32Seq,
                                                &numCodePoints,
                                                &numBytes,
                                                '?',
                                                oppositeEndian)
                            : Util::utf32ToUtf8(outBuf,
                                                len,
                                                utf32Seq,
                                                &numCodePoints,
                                                &numBytes)
                          : Util::utf32ToUtf8(outBuf,
                                              len,
                                              utf32Seq,
                                              &numCodePoints)
                        : Util::utf32ToUtf8(outBuf,
                                            len,
                                            utf32Seq);

                    LOOP4_ASSERT(LINE, len, expectedNumBytes, numBytes,
                                 !checkNBytes || expectedNumBytes == numBytes);
                    ASSERT(!checkNumCPs ||
                                       expectedNumCodePoints == numCodePoints);

                    LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);

                    LOOP2_ASSERT(LINE, len,
                           0 == len || 0 == bsl::memcmp(outBuf, &compareStr[0],
                                                        expectedNumBytes - 1));
                    LOOP2_ASSERT(LINE, len,
                                0 == len || 0 == outBuf[expectedNumBytes - 1]);
                }
            }
        }
      } break;
      case 6: {
        // --------------------------------------------------------------------
        // Testing UTF-8 -> UTF-32 OTHER VALUES OF ERRORCHAR
        //
        // Concerns:
        //   That values of 'errorWord' other than 'default' and 0 work
        //   correctly.
        //
        // Plan:
        //   Repeat the first loop of the vector test in case 3 with multiple
        //   values of 'errorWord' other than 0 and verify that the specified
        //   code point is properly substituted.  Only do those cases where
        //   'IS_ERROR' is true and 'IS_TRUNC' is 0.  Repeat for string refs
        //   and both byte orders.
        // --------------------------------------------------------------------

        if (verbose) cout <<
                         "Testing UTF-8 -> UTF-32 OTHER VALUES OF ERRORCHAR\n"
                         "=================================================\n";

        static unsigned int errorWords[] = { 1, 10, 20, 'a', 'A', 256, 500,
                          1000, 10 * 1000, 0xd7ff, 0xe000, 1 << 20, 0x10ffff };
        enum { NUM_ERROR_WORDS = sizeof errorWords / sizeof *errorWords };

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int   ti            = tm % NUM_UTF8_TABLE;
            const bool  useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool  opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const char *UTF8_STRING   = utf8Table[ti].d_utf8String;
            const bool  IS_ERROR      = utf8Table[ti].d_error;
            const int   TRUNC_BY      = utf8Table[ti].d_truncBy;

            if (!IS_ERROR || TRUNC_BY) {
                continue;
            }

            for (int te = 0; te < NUM_ERROR_WORDS; ++te) {
                const unsigned int ERROR_WORD = errorWords[te];

                if (veryVeryVerbose) { P_(ti); P_(UTF8_STRING); P(te); }

                unsigned int expectedOut[] = { '1', ERROR_WORD, 'z', 0 };
                if (opposite) {
                    for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                        expectedOut[u] = sb(expectedOut[u]);
                    }
                }
                int expectedRet = Status::k_INVALID_INPUT_BIT;
                const unsigned expectedWords = 4;

                bsl::vector<unsigned int> outVec;
                const PaddedStringRef sr(UTF8_STRING);
                int ret = useStringRef
                        ? opposite
                          ? Util::utf8ToUtf32(&outVec,
                                              sr,
                                              ERROR_WORD,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(&outVec,
                                              sr,
                                              ERROR_WORD)
                        : opposite
                          ? Util::utf8ToUtf32(&outVec,
                                              UTF8_STRING,
                                              ERROR_WORD,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(&outVec,
                                              UTF8_STRING,
                                              ERROR_WORD);
                ASSERT(expectedRet == ret);
                ASSERT(expectedWords == outVec.size());
                ASSERT(0 == outVec.back());

                const bsl::size_t expectedMatch = 4 * sizeof(unsigned int);

                ASSERT(0 == bsl::memcmp(outVec.begin(), expectedOut,
                                                               expectedMatch));

                unsigned int swappedErrorWord = opposite ? sb(ERROR_WORD)
                                                         : ERROR_WORD;
                LOOP3_ASSERT(ti, hx(swappedErrorWord), hx(outVec[1]),
                                                swappedErrorWord == outVec[1]);
            }
        }
      } break;
      case 5: {
        // --------------------------------------------------------------------
        // Testing UTF-8 -> UTF-32 Buffer Transl'n With 0 for errChr, to Vector
        //
        // Concerns:
        //   That 'utf8ToUtf32' called with vector output performs as expected:
        //: 1 Test sound encodings of minimal and maximal encoded values for
        //:   UTF-8 sequences 1, 2, 3, and 4 octets long.
        //: 2 Test non-minimal encodings -- values 1 too small, and zero
        //:   encodings
        //: 3 Test 5 octet encodings (always taken to be illegal)
        //: 4 Test truncated encodings.
        //: 5 Repeat test for the following configurations
        //:   o Preceded by, and followed by, valid ASCII bytes
        //:   o At beginning of string
        //:   o At end of string
        //:   o Followed by a lone continuation char
        //: 6 Test input from 'const char *' and string ref
        //: 7 Test both byte orders
        //
        // Plan:
        //   Repeat the plan for TC 4, except tailored to vector, rather than
        //   buffer, output.
        // --------------------------------------------------------------------

        if (verbose) cout <<
              "UTF-8 -> UTF-32 Buffer Transl'n With 0 for errChr, to Vector\n"
              "============================================================\n";

        if (verbose) Q(4-char sequences);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            unsigned int expectedOut[] = { '1', midVal, 'z', 0 };
            if (IS_ERROR) {
                bsl::memmove(&expectedOut[1], &expectedOut[2],
                                                     2 * sizeof(unsigned int));
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }

            const int expectedRet = IS_ERROR
                                         ? Status::k_INVALID_INPUT_BIT : 0;
            const unsigned expectedWords = 3 + !IS_ERROR;

            bsl::vector<unsigned int> outVec;
            const PaddedStringRef sr(UTF8_STRING);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          UTF8_STRING,
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          UTF8_STRING,
                                          0);
            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            LOOP3_ASSERT(LINE, expectedWords, outVec.size(),
                                               expectedWords == outVec.size());
            LOOP2_ASSERT(LINE, expectedWords, 0 == outVec.back());
            bsl::size_t expectedMatch = expectedWords * sizeof(unsigned int);
            ASSERT(0 == bsl::memcmp(&outVec[0], expectedOut, expectedMatch));
        }

        if (verbose) Q(Skipping first char);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;
            ++UTF8_STRING;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            unsigned int expectedOut[] = { midVal, 'z', 0 };
            if (IS_ERROR) {
                expectedOut[0] = 'z';
                expectedOut[1] = 0;
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }

            int expectedRet = IS_ERROR ? Status::k_INVALID_INPUT_BIT : 0;
            const unsigned expectedWords = IS_ERROR ? 2 : 3;

            bsl::vector<unsigned int> outVec;
            const PaddedStringRef sr(UTF8_STRING);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          UTF8_STRING,
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          UTF8_STRING,
                                          0);
            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(expectedWords == outVec.size());
            ASSERT(0 == outVec.back());

            const bsl::size_t expectedMatch = expectedWords *
                                                          sizeof(unsigned int);
            ASSERT(0 == bsl::memcmp(&outVec[0], expectedOut, expectedMatch));
        }

        if (verbose) Q(Eliminating last char);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;

            bsl::string s = UTF8_STRING;
            ASSERT(s.length() > 0);
            ASSERT('z' == s.back());
            s.resize(s.length() - 1);

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            unsigned int expectedOut[] = { '1', midVal, 0 };
            if (IS_ERROR) {
                expectedOut[1] = 0;
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            int expectedRet = IS_ERROR ? Status::k_INVALID_INPUT_BIT : 0;
            const unsigned expectedWords = IS_ERROR ? 2 : 3;

            bsl::vector<unsigned int> outVec;
            PaddedStringRef sr(s);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          s.c_str(),
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          s.c_str(),
                                          0);
            ASSERT(expectedRet == ret);
            ASSERT(expectedWords == outVec.size());
            ASSERT(0 == outVec.back());

            const size_t expectedMatch = expectedWords * sizeof(unsigned int);
            LOOP4_ASSERT(useStringRef, opposite, LINE, IS_ERROR,
                     0 == bsl::memcmp(&outVec[0], expectedOut, expectedMatch));
        }

        if (verbose) Q(Replacing 'z' with continuation);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;
            const int     TRUNC_BY    = utf8Table[ti].d_truncBy;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            bsl::string s = UTF8_STRING;
            ASSERT(s.length() > 0);
            ASSERT('z' == s.back());
            s.back() = (char) 0x83;

            unsigned int expectedOut[] = { '1', midVal, 0 };
            if (IS_ERROR) {
                expectedOut[1] = 0;
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            const bool fiveOctet = (UTF8_STRING[1] & 0xf8) == 0xf8;
            int expectedRet;
            unsigned expectedWords;
            size_t expectedMatch;

            switch (TRUNC_BY) {
              case 0: {
                expectedRet = Status::k_INVALID_INPUT_BIT;
                expectedWords = IS_ERROR ? 2 : 3;
                expectedMatch = expectedWords;
              } break;
              case 1: {
                expectedRet = fiveOctet ? Status::k_INVALID_INPUT_BIT : 0;
                expectedWords = fiveOctet ? 2 : 3;
                expectedMatch = 1;
              } break;
              default: {    // 2 or more
                expectedRet = Status::k_INVALID_INPUT_BIT;
                expectedWords = 2;
                expectedMatch = expectedWords;
              }
            }
            expectedMatch *= sizeof(unsigned int);

            bsl::vector<unsigned int> outVec;
            PaddedStringRef sr(s);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          sr,
                                          0)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec,
                                          s.c_str(),
                                          0,
                                          oppositeEndian)
                      : Util::utf8ToUtf32(&outVec,
                                          s.c_str(),
                                          0);
            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            LOOP3_ASSERT(LINE, expectedWords, outVec.size(),
                                               expectedWords == outVec.size());
            ASSERT(0 == outVec.back());

            LOOP3_ASSERT(LINE, expectedMatch, TRUNC_BY,
                     0 == bsl::memcmp(&outVec[0], expectedOut, expectedMatch));
        }
      } break;
      case 4: {
        // --------------------------------------------------------------------
        // Testing UTF-8 -> UTF-32 Buffer Translation With 0 for errorWord
        //
        // Concerns:
        //   That 'utf8ToUtf32' called with buffer output performs as expected:
        //: 1 Test sound encodings of minimal and maximal encoded values for
        //:   UTF-8 sequences 1, 2, 3, and 4 octets long.
        //: 2 Test non-minimal encodings -- values 1 too small, and zero
        //:   encodings
        //: 3 Test 5 octet encodings (always taken to be illegal)
        //: 4 Test truncated encodings.
        //: 5 Repeat test for the following configurations
        //:   o Preceded by, and followed by, valid ASCII bytes
        //:   o At beginning of string
        //:   o At end of string
        //:   o Followed by a lone continuation char
        //: 6 Test with input from 'const char *'s and string refs.
        //: 7 Test with output being both byte orders
        //
        // Plan:
        //   Set up one loop for each of the case listed under '5' in the
        //   concerns.  The loops will call 'utf8ToUtf32', setting up variables
        //   first to anticipate what the expected behavior of this translation
        //   call.
        //: 1 Iterate through all the entries in the static array 'utf8Table'
        //:   above, to determine the input string to pass to the translation
        //:   call.
        //: 2 Iterate the value 'len', the capacity in words of the output
        //:   buffer, from 'more than enough room' down to zero, and pass 'len'
        //:   to the 'capacity' arg of 'utf8ToUtf32' on each call.
        //: 3 Calculate 'expectedRet', the expected return value for
        //:   'utf8ToUtf32' and, after the call, verify it is indeed the
        //:   return value.
        //: 4 Create an unsigned int array 'expectedOut' of the expected output
        //:   sequence, and calculate 'expectedMatch', the number of bytes of
        //:   it that are expected to match the translation output, and compare
        //:   to the output after the translation call.
        //: 5 Calculate 'expectedWords', the expected number of code points
        //:   output (including the terminating 0), and verify it is the value
        //:   of 'numCodePoints' returned by the translation call.
        //: 6 Calculate 'expectedMatch', the number of bytes of the output
        //:   which are expected to match 'expectedOut' from '5', note that
        //:   'expectedMatch' will vary with 'len'.  After the translation,
        //:   verify that the first 'expectedMatch' bytes of output match
        //:   expectedOut.
        // --------------------------------------------------------------------

        if (verbose) cout <<
                 "Testing UTF-8 -> UTF-32 Buffer Translation (0 for errChr)\n"
                 "=========================================================\n";

        const unsigned int fillWord = 0x10000;

        if (verbose) Q(4-char sequences);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            const int MAX_LEN = 5;
            unsigned int out32Buf[MAX_LEN];
            unsigned int expectedOut[] = { '1', midVal, 'z', 0 };
            if (IS_ERROR) {
                bsl::memmove(&expectedOut[1], &expectedOut[2],
                                                     2 * sizeof(unsigned int));
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            for (int len = MAX_LEN; len >= 0; --len) {
                bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                int expectedRet = IS_ERROR && len >= 3
                                  ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < (IS_ERROR ? 3 : 4)
                               ? Status::k_OUT_OF_SPACE_BIT : 0;
                const unsigned expectedCodePoints = bsl::min(len, 3+!IS_ERROR);

                bsl::size_t numCodePoints = -1;
                const PaddedStringRef sr(UTF8_STRING);
                int ret = useStringRef
                        ? opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              UTF8_STRING,
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              UTF8_STRING,
                                              &numCodePoints,
                                              0)
                        : opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0);
                LOOP4_ASSERT(LINE, len, expectedRet, ret, expectedRet == ret);
                LOOP3_ASSERT(LINE, expectedCodePoints, numCodePoints,
                                          expectedCodePoints == numCodePoints);
                LOOP3_ASSERT(LINE, len, expectedCodePoints,
                            0 == len || 0 == out32Buf[expectedCodePoints - 1]);
                int expectedMatch = 3 + !IS_ERROR;
                expectedMatch = len >= expectedMatch ? expectedMatch
                                                     : bsl::max(0, len - 1);
                ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                for (int i = 0; i < expectedMatch; ++i) {
                    LOOP6_ASSERT(LINE, len, expectedCodePoints, i, out32Buf[i],
                                expectedOut[i], out32Buf[i] == expectedOut[i]);
                }
            }
        }

        if (verbose) Q(Skipping first char);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;
            ++UTF8_STRING;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            const int MAX_LEN = 6;
            unsigned int out32Buf[MAX_LEN];
            unsigned int expectedOut[] = { midVal, 'z', 0 };
            if (IS_ERROR) {
                expectedOut[0] = 'z';
                expectedOut[1] = 0;
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }

            for (int len = MAX_LEN; len >= 0; --len) {
                bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                int expectedRet = IS_ERROR && len >= 2
                                  ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < (IS_ERROR ? 2 : 3)
                               ? Status::k_OUT_OF_SPACE_BIT : 0;
                const unsigned expectedCodePoints =
                                               bsl::min(len, IS_ERROR ? 2 : 3);

                bsl::size_t numCodePoints = -1;
                const PaddedStringRef sr(UTF8_STRING);
                int ret = useStringRef
                        ? opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0)
                        : opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              UTF8_STRING,
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              UTF8_STRING,
                                              &numCodePoints,
                                              0);
                LOOP4_ASSERT(LINE, len, expectedRet, ret, expectedRet == ret);
                ASSERT(expectedCodePoints == numCodePoints);
                ASSERT(0 == len || 0 == out32Buf[expectedCodePoints - 1]);

                ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                const size_t expectedMatch = (3 == expectedCodePoints ? 3 :
                                   bsl::max(0, (int) expectedCodePoints - 1)) *
                                                          sizeof(unsigned int);

                ASSERT(0 == bsl::memcmp(out32Buf, expectedOut, expectedMatch));
            }
        }

        if (verbose) Q(Eliminating last char);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;
            bsl::string s = UTF8_STRING;
            ASSERT(s.length() > 0);
            s.resize(s.length() - 1);

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            const int MAX_LEN = 5;
            unsigned int out32Buf[MAX_LEN];
            unsigned int expectedOut[] = { '1', midVal, 0 };
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            for (int len = MAX_LEN; len >= 0; --len) {
                bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                int expectedRet = IS_ERROR && len >= 3
                                  ? Status::k_INVALID_INPUT_BIT : 0;
                expectedRet |= len < 3
                               ? Status::k_OUT_OF_SPACE_BIT : 0;
                const unsigned expectedCodePoints =
                                           bsl::min(len, IS_ERROR ? 2 : 3);

                bsl::size_t numCodePoints = -1;
                PaddedStringRef sr(s);
                int ret = useStringRef
                        ? opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0)
                        : opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              s.c_str(),
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              s.c_str(),
                                              &numCodePoints,
                                              0);
                LOOP4_ASSERT(LINE, len, expectedRet, ret, expectedRet == ret);
                ASSERT(expectedCodePoints == numCodePoints);
                ASSERT(0 == len || 0 == out32Buf[expectedCodePoints - 1]);

                ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                const size_t expectedMatch = (3 == expectedCodePoints ? 3 :
                                   bsl::max(0, (int) expectedCodePoints - 1)) *
                                                          sizeof(unsigned int);

                ASSERT(0 == bsl::memcmp(out32Buf, expectedOut, expectedMatch));
            }
        }

        if (verbose) Q(Replacing 'z' with continuation);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            const int ti             = tm % NUM_UTF8_TABLE;
            const bool useStringRef  = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite      = (tm/NUM_UTF8_TABLE) & 2;

            const int     LINE        = utf8Table[ti].d_line;
            const char   *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int  midVal      = utf8Table[ti].d_midVal;
            const bool    IS_ERROR    = utf8Table[ti].d_error;
            const int     TRUNC_BY    = utf8Table[ti].d_truncBy;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            bsl::string s = UTF8_STRING;
            ASSERT(s.length() > 0);
            ASSERT('z' == s.back());
            s.back() = (char) 0x83;

            const int MAX_LEN = 6;
            unsigned int out32Buf[MAX_LEN];
            unsigned int expectedOut[] = { '1', midVal, 0 };
            if (IS_ERROR) {
                expectedOut[1] = 0;
            }
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            const bool fiveOctet = (UTF8_STRING[1] & 0xf8) == 0xf8;
            for (int len = MAX_LEN; len >= 0; --len) {
                bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                int expectedRet;
                unsigned expectedCodePoints;

                switch (TRUNC_BY) {
                  case 0: {
                    expectedRet = (IS_ERROR && len >= 3) || len >= 4
                                         ? Status::k_INVALID_INPUT_BIT : 0;
                    expectedRet |= len < (IS_ERROR ? 3 : 4)
                                  ? Status::k_OUT_OF_SPACE_BIT  : 0;
                    expectedCodePoints = bsl::min(len, IS_ERROR ? 2 : 3);
                  } break;
                  case 1: {
                    expectedRet = len < 3 ? Status::k_OUT_OF_SPACE_BIT : 0;
                    expectedRet |= len >= 3 && fiveOctet ?
                                           Status::k_INVALID_INPUT_BIT : 0;
                    expectedCodePoints = bsl::min(len, fiveOctet ? 2 : 3);
                  } break;
                  default: {    // 2 or more
                    expectedRet = len >= 3 ?
                                           Status::k_INVALID_INPUT_BIT : 0;
                    expectedRet |= len<3 ? Status::k_OUT_OF_SPACE_BIT : 0;
                    expectedCodePoints = bsl::min(len, 2);
                  }
                }

                size_t expectedMatch = bsl::max(0,
                       (!TRUNC_BY ? ((int) expectedCodePoints -
                       !!(expectedRet & Status::k_OUT_OF_SPACE_BIT)) :
                    bsl::min(len - 1, 1))) * sizeof(unsigned int);

                bsl::size_t numCodePoints = -1;
                PaddedStringRef sr(s);
                int ret = useStringRef
                        ? opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              sr,
                                              &numCodePoints,
                                              0)
                        : opposite
                          ? Util::utf8ToUtf32(out32Buf,
                                              len,
                                              s.c_str(),
                                              &numCodePoints,
                                              0,
                                              oppositeEndian)
                          : Util::utf8ToUtf32(out32Buf,
                                              len,
                                              s.c_str(),
                                              &numCodePoints,
                                              0);
                LOOP5_ASSERT(LINE, len, expectedRet, ret, TRUNC_BY,
                                                           expectedRet == ret);
                LOOP4_ASSERT(LINE, len, expectedCodePoints, numCodePoints,
                                          expectedCodePoints == numCodePoints);
                ASSERT(0 == numCodePoints || 0 == out32Buf[numCodePoints - 1]);

                ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                LOOP3_ASSERT(LINE, expectedMatch, len,
                            0 == bsl::memcmp(out32Buf, expectedOut,
                                                               expectedMatch));
            }
        }
      } break;
      case 3: {
        // --------------------------------------------------------------------
        // Testing UTF-8 -> UTF-32 Vector Translation
        //
        // Concerns:
        //: 1 That vector translation will size the vector appropriately
        //:   and produce the correct output.
        //
        // Plan:
        //: 1 Repeat the code for TC 2, expect this time make the output be
        //:   vector.
        //: 2 Note that much of the testing here involves safe asserts built
        //:   into the translation routine, since we're testing the exact
        //:   accuracy of the length-prediction function, which we can't test
        //:   directly since it is not public.
        // --------------------------------------------------------------------

        if (verbose) cout << "Testing UTF-8 -> UTF-32 Vector Translation\n"
                             "==========================================\n";

        if (verbose) Q(4-char sequences);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            int ti                          = tm % NUM_UTF8_TABLE;
            const bool useStringRef         = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite             = (tm/NUM_UTF8_TABLE) & 2;

            const int           LINE        = utf8Table[ti].d_line;
            const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int        midVal      = utf8Table[ti].d_midVal;
            const bool          IS_ERROR    = utf8Table[ti].d_error;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            unsigned int expectedOut[] = { '1', midVal, 'z', 0 };
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            int expectedRet = IS_ERROR ? Status::k_INVALID_INPUT_BIT : 0;
            const unsigned expectedCodePoints = 4;

            bsl::vector<unsigned int> outVec;
            PaddedStringRef sr(UTF8_STRING);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec, sr, '?', oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, sr)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec, UTF8_STRING, '?',
                                                               oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, UTF8_STRING);
            ASSERT(expectedRet == ret);
            LOOP4_ASSERT(useStringRef, LINE, expectedCodePoints, outVec.size(),
                                          expectedCodePoints == outVec.size());
            ASSERT(0 == outVec.back());

            const size_t expectedMatch = 4 * sizeof(unsigned int);

            ASSERT(0 == bsl::memcmp(outVec.begin(), expectedOut,
                                                               expectedMatch));

            LOOP3_ASSERT(ti, hx(midVal), hx(outVec[1]), midVal == outVec[1]);
        }

        if (verbose) Q(Skipping first char);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            int ti                          = tm % NUM_UTF8_TABLE;
            const bool useStringRef         = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite             = (tm/NUM_UTF8_TABLE) & 2;

            const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int        midVal      = utf8Table[ti].d_midVal;
            const bool          IS_ERROR    = utf8Table[ti].d_error;

            ++UTF8_STRING;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            unsigned int expectedOut[] = {  midVal, 'z', 0 };
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            bsl::vector<unsigned int> outVec;
            int expectedRet = IS_ERROR
                              ? Status::k_INVALID_INPUT_BIT : 0;
            const unsigned expectedCodePoints = 3;

            PaddedStringRef sr(UTF8_STRING);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec, sr, '?', oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, sr)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec, UTF8_STRING, '?',
                                                                oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, UTF8_STRING);

            ASSERT(expectedRet == ret);
            ASSERT(expectedCodePoints == outVec.size());
            ASSERT(0 == outVec.back());

            const size_t expectedMatch = 3 * sizeof(unsigned int);

            ASSERT(0 == bsl::memcmp(outVec.begin(),
                                    expectedOut,
                                    expectedMatch));

            LOOP3_ASSERT(ti, hx(midVal), hx(outVec[0]), midVal == outVec[0]);
        }

        if (verbose) Q(Eliminating last char);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            int ti                          = tm % NUM_UTF8_TABLE;
            const bool useStringRef         = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite             = (tm/NUM_UTF8_TABLE) & 2;

            const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int        midVal      = utf8Table[ti].d_midVal;
            const bool          IS_ERROR    = utf8Table[ti].d_error;
            bsl::string s = UTF8_STRING;
            ASSERT(s.length() > 0);
            s.resize(s.length() - 1);

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            unsigned int expectedOut[] = { '1',  midVal, 0 };
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            bsl::vector<unsigned int> outVec;
            int expectedRet = IS_ERROR
                              ? Status::k_INVALID_INPUT_BIT : 0;
            const unsigned expectedCodePoints = 3;

            PaddedStringRef sr(s);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec, sr, '?', oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, sr)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec, s.c_str(), '?',
                                                                oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, s.c_str());
            ASSERT(expectedRet == ret);
            ASSERT(expectedCodePoints == outVec.size());
            ASSERT(0 == outVec.back());

            const size_t expectedMatch = 3 * sizeof(unsigned int);

            ASSERT(0 == bsl::memcmp(outVec.begin(),
                                    expectedOut,
                                    expectedMatch));

            LOOP3_ASSERT(ti, hx(midVal), hx(outVec[1]), midVal == outVec[1]);
        }

        if (verbose) Q(Replacing 'z' with continuation);

        for (int tm = 0; tm < 4 * NUM_UTF8_TABLE; ++tm) {
            int ti                          = tm % NUM_UTF8_TABLE;
            const bool useStringRef         = (tm/NUM_UTF8_TABLE) & 1;
            const bool opposite             = (tm/NUM_UTF8_TABLE) & 2;

            const int           LINE        = utf8Table[ti].d_line;
            const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
            unsigned int        midVal      = utf8Table[ti].d_midVal;
            const int           TRUNC_BY    = utf8Table[ti].d_truncBy;

            if (veryVerbose) { P_(ti);  P(UTF8_STRING); }

            bsl::string s = UTF8_STRING;
            ASSERT(s.length() > 0);
            ASSERT('z' == s.back());
            s.back() = (char) 0x83;

            unsigned int expectedOut[] = { '1',  midVal, '?', 0 };
            if (opposite) {
                for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                    expectedOut[u] = sb(expectedOut[u]);
                }
                midVal = sb(midVal);
            }
            bsl::vector<unsigned int> outVec;
            int expectedRet;
            unsigned expectedCodePoints;
            size_t expectedMatch;

            switch (TRUNC_BY) {
              case 0: {
                expectedRet = Status::k_INVALID_INPUT_BIT;
                expectedCodePoints = 4;
                expectedMatch = 4 * sizeof(unsigned int);
              } break;
              case 1: {
                expectedRet = (UTF8_STRING[1] & 0xf8) == 0xf8 ?
                                           Status::k_INVALID_INPUT_BIT : 0;
                expectedCodePoints = 3;
                expectedMatch = sizeof(unsigned int);
              } break;
              default: {    // 2 or more
                expectedRet = Status::k_INVALID_INPUT_BIT;
                expectedCodePoints = 3;
                expectedMatch = 3 * sizeof(unsigned int);
                expectedOut[2] = 0;
              }
            }

            PaddedStringRef sr(s);
            int ret = useStringRef
                    ? opposite
                      ? Util::utf8ToUtf32(&outVec, sr, '?', oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, sr)
                    : opposite
                      ? Util::utf8ToUtf32(&outVec, s.c_str(), '?',
                                                                oppositeEndian)
                      : Util::utf8ToUtf32(&outVec, s.c_str());
            LOOP3_ASSERT(LINE, expectedRet, ret, expectedRet == ret);
            ASSERT(expectedCodePoints == outVec.size());
            ASSERT(0 == outVec.back());

            LOOP2_ASSERT(LINE, expectedMatch,
                            0 == bsl::memcmp(outVec.begin(), expectedOut,
                                                               expectedMatch));

            if (1 != TRUNC_BY) {
                LOOP3_ASSERT(LINE, hx(midVal), hx(outVec[1]),
                                                          midVal == outVec[1]);
            }
        }
      } break;
      case 2: {
        // --------------------------------------------------------------------
        // Testing UTF-8 -> UTF-32 Buffer Translation
        //
        // Concerns:
        //   That 'utf8ToUtf32' called with buffer output performs as expected:
        //: 1 Test sound encodings of minimal and maximal encoded values for
        //:   UTF-8 sequences 1, 2, 3, and 4 octets long.
        //: 2 Test non-minimal encodings -- values 1 too small, and zero
        //:   encodings
        //: 3 Test 5 octet encodings (always taken to be illegal)
        //: 4 Test truncated encodings.
        //: 5 Repeat test for the following configurations
        //:   o Preceded by, and followed by, valid ASCII bytes
        //:   o At beginning of string
        //:   o At end of string
        //:   o Followed by a lone continuation char
        //: 6 Repeat all tests with both byte orders.
        //
        // Plan:
        //   Set up one loop for each of the case listed under '5' in the
        //   concerns.  The loops will call 'utf8ToUtf32', setting up variables
        //   first to anticipate what the expected behavior of this translation
        //   call.
        //: 1 Iterate eight times over the variable 'mode', driving 3 booleans:
        //:   o checkNumCPs -- have 'numCodePoints' returned and verify
        //:     accuracy
        //:   o useStringRef -- pass input as a string ref rather than a
        //:     'const char *'
        //:   o opposite -- use the opposite of host byte order
        //: 2 Within the loop of '1', iterate through all the entries in the
        //:   static array 'utf8Table' above, to determine the input string to
        //:   pass to the translation call.
        //: 3 Iterate the value 'len', the capacity in words of the output
        //:   buffer, from 'more than enough room' down to zero, and pass 'len'
        //:   to the 'capacity' arg of 'utf8ToUtf32' on each call.
        //: 4 Calculate 'expectedRet', the expected return value for
        //:   'utf8ToUtf32' and, after the call, verify it is indeed the return
        //:   value.
        //: 5 Create an unsigned int array 'expectedOut' of the expected output
        //:   sequence, and calculate 'expectedMatch', the number of bytes of
        //:   it that are expected to match the translation output, and compare
        //:   to the output after the translation call.
        //: 6 Calculate 'expectedCodePoints', the expected number of code
        //:   points output (including the terminating 0), and verify it is the
        //:   value of 'numCodePoints' returned by the translation call (if'
        //:   checkNumCPs' is true, meaning 'numCodePoints' is passed to the
        //:   translation call).
        //: 7 Calculate 'expectedMatch', the number of bytes of the output
        //:   which are expected to match 'expectedOut' from '5', note that
        //:   'expectedMatch' will vary with 'len'.  After the translation,
        //:   verify that the first 'expectedMatch' bytes of output match
        //:   expectedOut.
        // --------------------------------------------------------------------

        if (verbose) cout << "Testing UTF-8 -> UTF-32 Buffer Translation\n"
                             "==========================================\n";

        const unsigned int fillWord = 0x10000;

        if (verbose) Q(4-char sequences);

        for (int mode = 0; mode < 8; ++mode) {
            const bool checkNumCPs  = 0 != (1 & mode);
            const bool useStringRef = 0 != (2 & mode);
            const bool opposite     = 0 != (4 & mode);

            if (opposite && !checkNumCPs) {
                continue;
            }

            for (int ti = 0; ti < NUM_UTF8_TABLE; ++ti) {
                const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
                const unsigned int  MID_VAL     = utf8Table[ti].d_midVal;
                const bool          IS_ERROR    = utf8Table[ti].d_error;

                const int MAX_LEN = 6;
                unsigned int out32Buf[MAX_LEN];
                unsigned int expectedOut[] = { '1', MID_VAL, 'z', 0 };
                if (opposite) {
                    for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                        expectedOut[u] =
                                bsls::ByteOrderUtil::swapBytes(expectedOut[u]);
                    }
                }

                for (int len = MAX_LEN; len >= 0; --len) {
                    bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                    int expectedRet = IS_ERROR && len > 2
                                      ? Status::k_INVALID_INPUT_BIT : 0;
                    expectedRet |= len < 4
                                   ? Status::k_OUT_OF_SPACE_BIT : 0;
                    const unsigned expectedCodePoints = bsl::min(len, 4);

                    if (veryVeryVeryVerbose) { P_(mode); P_(ti); P(len); }

                    bsl::size_t numCodePoints = -1;
                    PaddedStringRef sr(UTF8_STRING);
                    int ret = useStringRef
                            ? (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    sr))
                            : (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       UTF8_STRING,
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       UTF8_STRING,
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    UTF8_STRING));
                    LOOP4_ASSERT(ti, len, expectedRet, ret,
                                                           expectedRet == ret);
                    ASSERT(!checkNumCPs ||
                                          expectedCodePoints == numCodePoints);
                    ASSERT(0 == len || 0 == out32Buf[expectedCodePoints - 1]);

                    const size_t expectedMatch =
                                          (len >= 4 ? 4 : bsl::max(len - 1, 0))
                                                        * sizeof(unsigned int);

                    ASSERT(0 == bsl::memcmp(out32Buf, expectedOut,
                                                               expectedMatch));

                    ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                    if (len >= 3) {
                        if (opposite) {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[1]),
                                     bsls::ByteOrderUtil::swapBytes(MID_VAL) ==
                                                                  out32Buf[1]);
                        }
                        else {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[1]),
                                                       MID_VAL == out32Buf[1]);
                        }
                    }
                }
            }
        }

        if (verbose) Q(Skipping first char);

        for (int mode = 0; mode < 8; ++mode) {
            const bool checkNumCPs  = 0 != (1 & mode);
            const bool useStringRef = 0 != (2 & mode);
            const bool opposite     = 0 != (4 & mode);

            if (opposite && !checkNumCPs) {
                continue;
            }

            for (int ti = 0; ti < NUM_UTF8_TABLE; ++ti) {
                const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
                const unsigned int  MID_VAL     = utf8Table[ti].d_midVal;
                const bool          IS_ERROR    = utf8Table[ti].d_error;
                ++UTF8_STRING;

                const int MAX_LEN = 6;
                unsigned int out32Buf[MAX_LEN];
                unsigned int expectedOut[] = { MID_VAL, 'z', 0 };
                if (opposite) {
                    for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                        expectedOut[u] = bsls::ByteOrderUtil::swapBytes(
                                                               expectedOut[u]);
                    }
                }
                for (int len = MAX_LEN; len >= 0; --len) {
                    bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                    int expectedRet = IS_ERROR && len > 1
                                      ? Status::k_INVALID_INPUT_BIT : 0;
                    expectedRet |= len < 3
                                   ? Status::k_OUT_OF_SPACE_BIT : 0;
                    const unsigned expectedCodePoints = bsl::min(len, 3);

                    bsl::size_t numCodePoints = -1;
                    PaddedStringRef sr(UTF8_STRING);
                    int ret = useStringRef
                            ? (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    sr))
                            : (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       UTF8_STRING,
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       UTF8_STRING,
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    UTF8_STRING));
                    ASSERT(expectedRet == ret);
                    ASSERT(!checkNumCPs ||
                                          expectedCodePoints == numCodePoints);
                    ASSERT(0 == len || 0 == out32Buf[expectedCodePoints - 1]);

                    const size_t expectedMatch =
                                          (len >= 3 ? 3 : bsl::max(len - 1, 0))
                                                        * sizeof(unsigned int);

                    ASSERT(0 == bsl::memcmp(out32Buf, expectedOut,
                                                               expectedMatch));

                    ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                    if (len >= 2) {
                        if (opposite) {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[0]),
                                     bsls::ByteOrderUtil::swapBytes(MID_VAL) ==
                                                                  out32Buf[0]);
                        }
                        else {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[0]),
                                                       MID_VAL == out32Buf[0]);
                        }
                    }
                }
            }
        }

        if (verbose) Q(Eliminating last char);

        for (int mode = 0; mode < 8; ++mode) {
            const bool checkNumCPs  = 0 != (1 & mode);
            const bool useStringRef = 0 != (2 & mode);
            const bool opposite     = 0 != (4 & mode);

            if (opposite && !checkNumCPs) {
                continue;
            }

            for (int ti = 0; ti < NUM_UTF8_TABLE; ++ti) {
                const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
                const unsigned int  MID_VAL     = utf8Table[ti].d_midVal;
                const bool          IS_ERROR    = utf8Table[ti].d_error;
                bsl::string s = UTF8_STRING;
                ASSERT(s.length() > 0);
                s.resize(s.length() - 1);

                const int MAX_LEN = 5;
                unsigned int out32Buf[MAX_LEN];
                unsigned int expectedOut[] = { '1', MID_VAL, 0 };
                if (opposite) {
                    for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                        expectedOut[u] = bsls::ByteOrderUtil::swapBytes(
                                                               expectedOut[u]);
                    }
                }
                for (int len = MAX_LEN; len >= 0; --len) {
                    bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                    int expectedRet = IS_ERROR && len >= 3
                                      ? Status::k_INVALID_INPUT_BIT : 0;
                    expectedRet |= len < 3
                                   ? Status::k_OUT_OF_SPACE_BIT : 0;
                    const unsigned expectedCodePoints = bsl::min(len, 3);

                    bsl::size_t numCodePoints = -1;
                    PaddedStringRef sr(s);
                    int ret = useStringRef
                            ? (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    sr))
                            : (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       s.c_str(),
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       s.c_str(),
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    s.c_str()));
                    ASSERT(expectedRet == ret);
                    ASSERT(!checkNumCPs ||
                                          expectedCodePoints == numCodePoints);
                    ASSERT(0 == len || 0 == out32Buf[expectedCodePoints - 1]);

                    const size_t expectedMatch =
                                          (len >= 3 ? 3 : bsl::max(len - 1, 0))
                                                        * sizeof(unsigned int);

                    ASSERT(0 == bsl::memcmp(out32Buf, expectedOut,
                                                               expectedMatch));

                    ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                    if (len >= 3) {
                        if (opposite) {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[0]),
                                     bsls::ByteOrderUtil::swapBytes(MID_VAL) ==
                                                                  out32Buf[1]);
                        }
                        else {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[0]),
                                                       MID_VAL == out32Buf[1]);
                        }
                    }
                }
            }
        }

        if (verbose) Q(Replacing 'z' with continuation);

        for (int mode = 0; mode < 8; ++mode) {
            const bool checkNumCPs  = 0 != (1 & mode);
            const bool useStringRef = 0 != (2 & mode);
            const bool opposite     = 0 != (4 & mode);

            if (opposite && !checkNumCPs) {
                continue;
            }

            for (int ti = 0; ti < NUM_UTF8_TABLE; ++ti) {
                const int           LINE        = utf8Table[ti].d_line;
                const char         *UTF8_STRING = utf8Table[ti].d_utf8String;
                const unsigned int  MID_VAL     = utf8Table[ti].d_midVal;
                const bool          IS_ERROR    = utf8Table[ti].d_error;
                const int           TRUNC_BY    = utf8Table[ti].d_truncBy;

                bsl::string s = UTF8_STRING;
                ASSERT(s.length() > 0);
                ASSERT('z' == s.back());
                s.back() = (char) 0x83;

                const int MAX_LEN = 6;
                unsigned int out32Buf[MAX_LEN];
                unsigned int expectedOut[] = { '1', MID_VAL, '?', 0 };
                if (opposite) {
                    for (unsigned u = 0; u < sizeof(expectedOut)/sizeof(int);
                                                                         ++u) {
                        expectedOut[u] = bsls::ByteOrderUtil::swapBytes(
                                                               expectedOut[u]);
                    }
                }
                for (int len = MAX_LEN; len >= 0; --len) {
                    bsl::fill(out32Buf + 0, out32Buf + MAX_LEN, fillWord);
                    int expectedRet;
                    unsigned expectedCodePoints;
                    size_t expectedMatch;

                    switch (TRUNC_BY) {
                      case 0: {
                        expectedRet = (IS_ERROR && len >= 3) || len >= 4
                                      ? Status::k_INVALID_INPUT_BIT : 0;
                        expectedRet |= len < 4
                                      ? Status::k_OUT_OF_SPACE_BIT  : 0;
                        expectedCodePoints = bsl::min(len, 4);
                        expectedMatch =(len >= 4 ? 4 : bsl::max(len - 1, 0))
                                                        * sizeof(unsigned int);
                      } break;
                      case 1: {
                        expectedRet = len < 3
                                      ? Status::k_OUT_OF_SPACE_BIT  : 0;
                        expectedRet |= len >= 3 &&
                                              (UTF8_STRING[1] & 0xf8) == 0xf8 ?
                                           Status::k_INVALID_INPUT_BIT : 0;
                        expectedCodePoints = bsl::min(len, 3);
                        expectedMatch = bsl::max(0, bsl::min(len - 1, 1)) *
                                                          sizeof(unsigned int);
                      } break;
                      default: {    // 2 or more
                        expectedRet = len >= 3 ?
                                           Status::k_INVALID_INPUT_BIT : 0;
                        expectedRet |= len < 3
                                       ? Status::k_OUT_OF_SPACE_BIT : 0;
                        expectedCodePoints = bsl::min(len, 3);
                        expectedMatch = (len >= 3 ? 3 : bsl::max(len - 1, 0))
                                                        * sizeof(unsigned int);
                        expectedOut[2] = 0;
                      }
                    }

                    bsl::size_t numCodePoints = -1;
                    PaddedStringRef sr(s);
                    int ret = useStringRef
                            ? (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       sr,
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    sr))
                            : (checkNumCPs
                                ? (opposite
                                   ? Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       s.c_str(),
                                                       &numCodePoints,
                                                       '?',
                                                       oppositeEndian)
                                   : Util::utf8ToUtf32(out32Buf,
                                                       len,
                                                       s.c_str(),
                                                       &numCodePoints))
                                : Util::utf8ToUtf32(out32Buf,
                                                    len,
                                                    s.c_str()));
                    LOOP5_ASSERT(LINE, len, expectedRet, ret, TRUNC_BY,
                                                           expectedRet == ret);
                    ASSERT(!checkNumCPs ||
                                          expectedCodePoints == numCodePoints);
                    ASSERT(0 == len || 0 == out32Buf[expectedCodePoints - 1]);

                    LOOP3_ASSERT(LINE, expectedMatch, len,
                                0 == bsl::memcmp(out32Buf, expectedOut,
                                                               expectedMatch));

                    ASSERT(out32Buf + MAX_LEN ==
                               bsl::find_if(out32Buf + expectedCodePoints,
                                            out32Buf + MAX_LEN,
                                            NotEqual<unsigned int>(fillWord)));
                    if (len >= 3 && TRUNC_BY != 1) {
                        if (opposite) {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[0]),
                                     bsls::ByteOrderUtil::swapBytes(MID_VAL) ==
                                                                  out32Buf[1]);
                        }
                        else {
                            LOOP3_ASSERT(ti, MID_VAL, hx(out32Buf[0]),
                                                       MID_VAL == out32Buf[1]);
                        }
                    }
                }
            }
        }
      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST
        //
        // Plan:
        //   Translate a sequence, with no errors, from UTF-8 to UTF-32 and
        //   back.
        // --------------------------------------------------------------------

        const char *utf8 = "H" "e" "l" "l" "o" "\n"   // ASCII
                           "\xcb\xb1" "\n"            // 2-char UTF-8 753
                           "\xe2\x9c\x90" "\n"        // 3-char UTF-8 10000
                           "\xf0\x98\x9a\xa0" "\n";   // 4-char UTF-8 100000

        unsigned int utf32[100];
        bsl::size_t numCodePoints, numBytes;

        int sts = Util::utf8ToUtf32(utf32,
                                    100,
                                    utf8,
                                    &numCodePoints);
        ASSERT(0 == sts);
        ASSERT(13 == numCodePoints);
        ASSERT(0 == utf32[numCodePoints - 1]);

        const unsigned *putf32 = utf32;

        ASSERT(*putf32++ == 'H');
        ASSERT(*putf32++ == 'e');
        ASSERT(*putf32++ == 'l');
        ASSERT(*putf32++ == 'l');
        ASSERT(*putf32++ == 'o');
        ASSERT(*putf32++ == '\n');
        ASSERT(*putf32++ == 753);
        ASSERT(*putf32++ == '\n');
        ASSERT(*putf32++ == 10000);
        ASSERT(*putf32++ == '\n');
        ASSERT(*putf32++ == 100000);
        ASSERT(*putf32++ == '\n');
        ASSERT(*putf32++ == 0);

        char utf8Out[100];

        numCodePoints = numBytes = -1;
        sts = Util::utf32ToUtf8(utf8Out,
                                100,
                                utf32,
                                &numCodePoints,
                                &numBytes);
        ASSERT(0  == sts);
        ASSERT(13 == numCodePoints);
        ASSERT( bsl::strlen(utf8) + 1 == numBytes);
        ASSERT(!bsl::strcmp(utf8, utf8Out));
      } break;
      case -1: {
        namespace TC = CASE_MINUS_1_NAMESPACE;

        const unsigned chars[] = { 'H', 'e', 'l', 'l', 'o', '\n',
                                   753, 10000, 100000, 0xd7ff, 0xe000,
                                   0xd800, 0xd8ff, 0xdc00, 0xdcff, 0xdd99,
                                   0x1f609, 0 };
        for (const unsigned *pu = chars; *pu; ++pu) {
            unsigned seq32[] = { *pu, 0 };
            bsl::string seq8;
            bool valid = !bdlde::CharConvertUtf32::utf32ToUtf8(&seq8, seq32);
            cout << bsl::hex << *pu << bsl::dec << ": ";
            TC::outputSequence(cout, *pu) << ": " << (valid ? "" : "in") <<
            "valid: " << seq8 << '\n';
        }
      } break;
      default: {
        cerr << "WARNING: CASE `" << test << "' NOT FOUND." << endl;
        testStatus = -1;
      }
    }

    return testStatus;
}

// ----------------------------------------------------------------------------
// Copyright 2017 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
